简体   繁体   中英

Issues with circular bit-shift in C++

I'm attempting to implement circular bit-shifting in C++. It kind of works, except after a certain point I get a bunch of zeroes.

for (int n=0;n<12;n++) {
    unsigned char x=0x0f;
    x=((x<<n)|(x>>(8-n))); //chars are 8 bits
    cout<<hex<<"0x"<<(int)x<<endl;
}

My output is:

0xf
0x1e
0x3c
0x78
0xf0
0xe1
0xc3
0x87
0xf
0x0
0x0
0x0

As you can see, I start getting 0x0's instead of the expected 0x1e, 0x3c, etc.

If I expand the for loop to iterate 60 times or so, the numbers come back correctly (after a bunch of zeroes.)

I'm assuming that a char houses a big space, and the "gaps" of unused data are zeroes. My understanding is a bit limited, so any suggestions would be appreciated. Is there a way to toss out those zeroes?

Shifting by a negative amount is undefined behavior.

You loop from 0 to 12 , but you have an 8 - n in your shifts. So that will go negative.

If you want to handle n > 8 , you'll need to take a modulus by 8. (assuming you want 8-bit circular shift.)


for (int n=0; n < 12; n++) {
    unsigned char x = 0x0f;
    int shift = n % 8;   //  Wrap modulus
    x = ((x << shift) | (x >> (8 - shift))); //chars are 8 bits
    cout << hex << "0x" << (int)x << endl;
}

Shifting a byte left by more than 7 will always result in 0. Also, shifting by a negative amount is not defined.

In order to fix this you have to limit the shift to the size of the type.

Basically:

unsigned char x = 0xf;
int shift = n&7;
x=((x<<shift)|(x>>(8-shift)))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM