Closed ajo-em closed 2 months ago
Curious, I don't see that behaviour...
test start unsigned left shift ui64=40000000 ui64=80000000 ui64=100000000 signed left shift i64=40000000 i64=80000000 i64=100000000 signed right shift i64=c000000000000000 i64=c000000000000000 test end
sResult = i64 << 31; // returns 0xFFFF FFFF 8000 0000 --> this is not OK !
This seems like the shifted 32 bits are being sign extended to 64 bits, which your code shouldn't/doesn't do; what compiler are you using, are you using debug... it seems like an unlikely bug even in an ancient GCC compiler tho.
Thanks for your help !!
My GCC-version is 13.2.1 20231009 ( not so very ancient )
I used it in Debug-Mode. But there was the same result with Release-Mode.
Meanwhile I could find the cause of the seen behavior ! Your comments lead me to the suspicion that there were data types used and eventually were internally converted which I did not expect.
These changes helped :
i32_arr[i] = 0x80000000 >> i; -----> i32_arr[i] = (int32_t)0x80000000 >> i;
ui64_arr[i] = 0x01 << i; -----> ui64_arr[i] = (uint64_t)0x01 << i;
i64_arr[i] = 0x01 << i; -----> i64_arr[i] = (int64_t)0x01 << i;
i64_arr[i] = 0x8000000000000000 >> i; -----> i64_arr[i] = (int64_t)0x8000000000000000 >> i;
Yeah, need to be careful with that. From cppreference "The type of the integer literal is the first type in which the value can fit...". Extra bits are not added when you shift past the bit size of the type. So you should specify your literal as the type you actually want as a result of the operation.
Closing this. Please reopen if you disagree.
Error when left shifting uint64_t or int64_t
uint64_t ui64 = 0x01; int64_t i64 = 0x01; uint64_t uResult; int64_t sResult;
uResult = ui63 << 30; // returns 0x0000 0000 4000 000 --> this is OK ! uResult = ui63 << 31; // returns 0xFFFF FFFF 8000 0000 --> this is not OK ! uResult = ui63 << 32; // returns 0x000 0000 0000 0000 --> this is not OK !
sResult = i64 << 30; // returns 0x0000 0000 4000 000 --> this is OK ! sResult = i64 << 31; // returns 0xFFFF FFFF 8000 0000 --> this is not OK ! sResult = i64 << 32; // returns 0x000 0000 0000 0000 --> this is not OK !
Unexpected result when right shifting int64_t
As I read there is no exact definition for right shifting of signed intergers. There are implementations where MSB is copied when shifting right. (Which I would prefer !) It's also OK if zero is shifted in from left side.
I would expect that there is the same result, if the shift width is a constant number or if it a variable. My experiment was to shift by 1 in a loop and also shift by a width defined by variable. My expectation was, that there is the same result. But it is Not !
int64_t i64 = 0x8000 0000 0000 0000; int16_t n = 1;
sResult = i64 >> 1; // returns 0xC000 0000 0000 0000
sResult = i64 >> n; // returns 0x4000 0000 0000 0000
right shifting int32_t has the same effect:
shifting by n shifts in zeroes, while shifting by 1 shifts in MSB
Here is some code I used for testing:
(small edit by lurch to put code-block in backticks)