简体   繁体   English

为什么在执行特定的按位运算时 uint64_t 的高 32 位变为 1?

[英]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);

Output:输出:

#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.

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