以下程序
#include <inttypes.h> /* printf(" %" PRIu32 "\n"), my_uint32_t) */
#include <stdio.h> /* printf(), perror() */
int main(int argc, char *argv[])
{
uint64_t u64 = ((unsigned char)0x80) << 24;
printf("%" PRIX64 "\n", u64);
/* uint64_t */ u64 = ((unsigned int)0x80) << 24;
printf("%016" PRIX64 "\n", u64);
}
产生
FFFFFFFF80000000
0000000080000000
在这种情况下,
((unsigned char)0x80)
和((unsigned int)0x80)
有什么区别?我猜
(unsigned char)0x80
被提升为(unsigned char)0xFFFFFFFFFFFFFF80
,然后被移位了,但是为什么这种转换认为unsigned char
是带符号的呢?有趣的是
0x80 << 16
产生了预期的结果0x0000000000800000
。 最佳答案
<<
运算符的左操作数进行整数提升。
这表示此表达式:
((unsigned char)0x80) << 24
等效于:
((int) (unsigned char)0x80) << 24
相当于:
0x80 << 24
在32位
int
系统中设置int
的符号位。然后,当在0x80 << 24
声明中将uint64_t
转换为u64
时,出现符号扩展名以产生值0xFFFFFFFF80000000
。编辑:
请注意,由于在注释中正确添加了Matt McNabb,从技术上来说
0x80 << 24
会调用C中的未定义行为,因为结果无法用<<
左操作数的类型表示。如果使用的是gcc
,则当前没有使该操作不确定的当前编译器版本guarantees。