在, 128 不适合您的 C 实现使用c1 = 128;
的有符号八位。char
128 转换为char
per C 2018 6.5.16.1 2:“右操作数的值转换为赋值表达式的类型……”</p>
转换是实现定义的,根据 6.3.1.3 3:“否则,新类型是有符号的,值不能在其中表示;结果要么是实现定义的,要么是产生实现定义的信号。” 您的 C 实现将 128(即 10000000 2作为无符号二进制数字)转换为 -128,当对有符号二进制使用二进制补码时,它用相同的位表示。因此,结果是c1
包含值 -128。
在printf("c1: %x, c2: %x\n", c1, c2);
,c1
被转换为int
. 这是因为使用...
参数调用函数的规则是将默认参数提升应用于相应的参数,根据 6.5.2.2 7:“默认参数提升是在尾随参数上执行的。”</p>
默认参数提升包括整数提升,根据 6.5.2.2 6。当 的范围char
小于int
时,就像在大多数 C 实现中一样,整数提升将 a 转换char
为int
,根据 6.3.1.1 2:“如果 anint
可以表示所有原始类型的值……,该值被转换为int
……”</p>
因此,在 中printf("c1: %x, c2: %x\n", c1, c2);
,int
-128 的值作为第二个参数传递。您的 C 实现使用 32 位二进制补码int
,其中 -128 用位 11111111111111111111111110000000 表示,我们可以用十六进制表示为 ffffff80。
格式字符串指定使用%x
. 正确的参数类型%x
是unsigned int
. 但是,您的 C 实现已接受int
并将其重新解释为unsigned int
. 因此,11111111111111111111111110000000 位被转换为字符串“ffffff80”。
这就解释了为什么要打印“ffffff80”。不是因为c1
有四个字节,而是因为它在传递给printf
. 此外,将负值转换为该四字节类型会导致设置了许多位的四个字节。
关于c1 == c2
评估为真(1),这仅仅是因为c1
如上所述被赋予值 -128,并且c2 = -128;
还将值 -128 分配给c2
,因此c1
和c2
具有相同的值。