[英]Why do the upper 32 bits of a uint64_t become one whilst performing a specific bitwise operation?
Can someone please explain to me why the upper 32 bits of a uint64_t
are set to one in case number #2:有人可以向我解释为什么
uint64_t
的高 32 位在第 2 种情况下设置为 1:
uint64_t ret = 0;
ret = (((uint64_t)0x00000000000000FF) << 24);
printf("#1 [%016llX]\n", ret);
ret = (0x00000000000000FF << 24);
printf("#2 [%016llX]\n", ret);
uint32_t ret2 = 0;
ret2 = (((uint32_t)0x000000FF) << 8);
printf("#3 [%08X]\n", ret2);
ret2 = (0x000000FF << 8);
printf("#4 [%08X]\n", ret2);
#1 [00000000FF000000]
#2 [FFFFFFFFFF000000]
#3 [0000FF00]
#4 [0000FF00]
https://ideone.com/xKUaTe https://ideone.com/xKUaTe
You'll notice I've given an "equivalent" 32bit version (cases #3 and #4) which doesn't show the same behaviour...你会注意到我给出了一个“等效”的 32 位版本(案例 #3 和 #4),它没有表现出相同的行为......
By default integer literals without a suffix will have type int
if they fit in an int
.默认情况下,如果没有后缀的整数文字适合
int
则它们的类型为int
。
The type of the integer constant
整数常量的类型
The type of the integer constant is the first type in which the value can fit, from the list of types which depends on which numeric base and which
integer-suffix
was used.整数常量的类型是值可以适合的第一种类型,来自类型列表,这取决于使用的数字基数和
integer-suffix
。
- no suffix
无后缀
- decimal bases:
十进制:
- int
整数
- long int
长整数
- unsigned long int (until C99)
unsigned long int(直到 C99)
- long long int (since C99)
long long int (C99 起)
- binary, octal, or hexadecimal bases:
二进制、八进制或十六进制基数:
- int
整数
- unsigned int
无符号整数
- long int
长整数
- unsigned long int
无符号长整数
- long long int (since C99)
long long int (C99 起)
- unsigned long long int (since C99)
unsigned long long int (C99 起)
- ...
...
As a result 0x00000000000000FF
will be an int
regardless of how many zeros you put in. You can check that by printing sizeof 0x00000000000000FF
因此,无论您输入多少个零,
0x00000000000000FF
都将是一个int
。您可以通过打印sizeof 0x00000000000000FF
来检查这一点
Therefore, 0x00000000000000FF << 24
results in 0xFF000000 which is a negative value 1 .因此,
0x00000000000000FF << 24
导致 0xFF000000 是负值1 。 That'll again be sign extended when casting to uint64_t
, filling the top 32 bits with ones当转换为
uint64_t
,这将再次被符号扩展,用 1 填充前 32 位
Casting help, as you can see in (uint64_t)0x00000000000000FF) << 24
, because now the shift operates on the uint64_t
value instead of int
.转换帮助,正如您在
(uint64_t)0x00000000000000FF) << 24
看到的,因为现在移位操作的是uint64_t
值而不是int
。 You can also use a suffix您也可以使用后缀
0x00000000000000FFU << 24
0x00000000000000FFULL << 24
The first line above does the shift in unsigned int
and then do zero extension to cast to uint64_t
.上面的第一行在
unsigned int
中进行移位,然后进行零扩展以uint64_t
转换为uint64_t
。 The second one does the operation in unsigned long long
directly第二个直接做
unsigned long long
的操作
0x000000FF << 8
doesn't expose the same behavior because the result is 0xFF00 which doesn't have the sign bit set, but it will if you do (int16_t)0x000000FF << 8
0x000000FF << 8
不会暴露相同的行为,因为结果是 0xFF00 没有设置符号位,但如果你这样做(int16_t)0x000000FF << 8
There are a lot of related and duplicate questions:有很多相关和重复的问题:
1 Technically shifting into the sign bit results in undefined behavior but in your case the compiler has chosen to leave the result the same as when you shift an unsigned value: 0xFFU << 24 = 0xFF000000U
which when converted to signed produces a negative value 1从技术上讲,移入符号位会导致未定义的行为,但在您的情况下,编译器选择将结果与移动无符号值时的结果相同:
0xFFU << 24 = 0xFF000000U
,当转换为有符号时会产生负值
See看
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.