有人可以向我解释一下为什么在第 #2 种情况下,uint64_t
的高 32 位设置为 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]
您会注意到我给出了一个“等效”32 位版本(案例 #3 和 #4),但它没有表现出相同的行为...
最佳答案
默认情况下,不带后缀的整数文字的类型为 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.
- no suffix
- decimal bases:
- int
- long int
- unsigned long int (until C99)
- long long int (since C99)
- binary, octal, or hexadecimal bases:
- int
- unsigned int
- long int
- unsigned long int
- long long int (since C99)
- unsigned long long int (since C99)
- ...
结果0x00000000000000FF
将是 int
不管你输入了多少个零。你可以通过打印 sizeof 0x00000000000000FF
来检查。
因此,0x00000000000000FF << 24
结果为 0xFF000000,这是一个负值1。当转换到 uint64_t
时,这将再次被符号扩展。 ,将高32位补为1
转换帮助,如 (uint64_t)0x00000000000000FF) << 24
中所示,因为现在类次在 uint64_t
上运行值而不是 int
。您还可以使用后缀
0x00000000000000FFU << 24
0x00000000000000FFULL << 24
上面的第一行在 unsigned int
中进行了转换然后进行零扩展以转换为 uint64_t
。第二个执行 unsigned long long
中的操作直接
0x000000FF << 8
不会暴露相同的行为,因为结果是 0xFF00,它没有设置符号位,但如果你这样做 (int16_t)0x000000FF << 8
就会出现这种情况
有很多相关和重复的问题:
- Type of integer literals not int by default?
- What Are Integer Literal Type? And How They Are Stored?
- what is the reason for explicitly declaring L or UL for long values
- ...
1 从技术上讲,转换到符号位会导致未定义的行为,但在您的情况下,编译器选择保留与转换无符号值时相同的结果:0xFFU << 24 = 0xFF000000U
当转换为有符号时会产生负值
查看
关于c - 为什么在执行特定的按位运算时,uint64_t 的高 32 位会变成 1?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33127326/