Tämän seurauksena
0b01 << 1
on
0b10
Mutta jos halutaan 0b11, niin kuinka se pitäisi tehdä?
0b01 << 1
on
0b10
Mutta jos halutaan 0b11, niin kuinka se pitäisi tehdä?
Turvaa tilisi vahvistamalla puhelinnumerosi. Voit silloin palauttaa unohtuneen salasanan tekstiviestillä.
Näihin keskusteluihin ei ole vielä vastattu. Ole ensimmäinen.
Vastaukset 11
Vanhimmat
Tein nyt purkkapatenttina makron, jossa siirretään ensin normaalisti vasemmalle, ja sitten ORilla ynnätään loppuun tarvittava määrä ykkösiä. Ei mikään tyylikkäin tapa, mutta vaikuttaisi toimivan. Jos jollain on järkevämpi vaihtoehto, niin vinkkiä voi antaa.
#define vasemmalle(luku,bitit) ((luku<<bitit)|((unsigned)0-1)>>((sizeof(luku)*8)-bitit))
Miksi noin monimutkainen jos vai pitää siirtaa vasemmalle ja lisätä ykkönen?
Sifti on erittäi nopea operaatio ja niin on myös ykkösen lisääminen. Kääntäjä muuttaa ykkösellä lisäämisen yhdeksi koneoperaatioksi missä ei ole edes parametria. Samoin sifti on yksi operaatio.
Mihin tuota bitit-parametiä tarvitaan jos kuitenkin siirretään yhdellä vasemmalle?
No+joo,+selitin+kyllä+aika+huonosti+mitä+olin+tekemässä.+Eli+tietysti+sen+yhden+bitin+siirto+käy+näppärärästi+kuvailemallasi+tavalla,+mutta+tässä+oli+tarve+shiftata+enemmänkin+kerralla.+Tuo+bitit-parametri+on+siis+se+shiftauksen+määrä.+Vähän+ehkä+tyhmä+nimivalinta,+mutta+en+nyt+jaksanut+keskittyä+epäolennaiseen.
Tässä+vielä+testiajo+0-9+bitin+siirtämisellä,+kun+käytetään+lukua+1.+Tuosta+huomaa+että+bitit-parametrillä+0+tulee+aivan+mitä+sattuu,+eli+nollan+käyttö+pitää+estää+jollain+muulla+tavalla.
Koodi:
---
#include+<stdio.h>
#define+vasemmalle(luku,bitit)+((luku<<bitit)|((unsigned)0-1)>>((sizeof(luku)*8)-bitit))
int+main(void);
int+main(void)+{
unsigned+long+luku=0b1;
char+i=0,bitti=0;
for(i=0;i<10;i++)+{
bitti=sizeof(luku)*8-1;
printf("vasemmalle(%lu,%d)+->+",luku,i);
while(bitti>=0)+{
if((vasemmalle(luku,i))&(1<<bitti))+printf("1");
else+printf("0");
if(bitti%8==0)+printf("+");
bitti--;
}
printf("\n");
}
return+0;
}
---
Tulos:
vasemmalle(1,0)+->+11111111+11111111+11111111+11111111+
vasemmalle(1,1)+->+00000000+00000000+00000000+00000011+
vasemmalle(1,2)+->+00000000+00000000+00000000+00000111+
vasemmalle(1,3)+->+00000000+00000000+00000000+00001111+
vasemmalle(1,4)+->+00000000+00000000+00000000+00011111+
vasemmalle(1,5)+->+00000000+00000000+00000000+00111111+
vasemmalle(1,6)+->+00000000+00000000+00000000+01111111+
vasemmalle(1,7)+->+00000000+00000000+00000000+11111111+
vasemmalle(1,8)+->+00000000+00000000+00000001+11111111+
vasemmalle(1,9)+->+00000000+00000000+00000011+11111111
olisit käyttänyt "latchea", eli assembly-komentoa RCR&RCL =rotate with carry..., single line...
(0b01 << 1) | 1
Tässä on se ongelma, että muuttaa myös kaikki muut bitit, kuin vain lisätyt bitit.
#define vasemmalle(luku,bitit) (~(~(luku)<<(bitit)))
Tässähän se.
Tuo on tyylikäs. Ensin lähtöluvun invertointi, sitten siirto joka täyttää nollilla, ja sitten koko luvun invertointi uudelleen, jolloin lisätyt nollat muuttuvat ykkösiksi.
Hieno oivallus! Ojennetaan nimimerkki Anonyymille virtuaalinen papukaijamerkki.
Se << siirtää bittejä vasemmalle ja täyttää nollia.
lisää yksi, ja täyttää sen oikeanpuolimmaisen siis ykkösellä.
Jos pitää täyttää ykkösillä ja siirtää useita kerralla niin silmukassa lisää yhden vasemmalle ja lisää yhden, ja toistaa sitä.
Joskus ratkaisua kannattaa hetken miettiä aivan oppimistarkoituksessakin. C-kieli on siitä jännä juttu, että yksinkertaisuudestaan huolimatta siinä riittää oppimista jopa vuosikymmeniksi. Ylläolevan makron pitäisi toimia ja vieläpä kaikilla integer-tyypeillä....vaikken olekaan testannut sitä.