以下程序

#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

10-08 07:11