C 无符号类型转换,并分配给不同字节大小的变量
有符号整数被分配给无符号整数。使用不同字节大小的无符号整数时,行为看起来有点奇怪 代码1:C 无符号类型转换,并分配给不同字节大小的变量,c,casting,unsigned,signed,C,Casting,Unsigned,Signed,有符号整数被分配给无符号整数。使用不同字节大小的无符号整数时,行为看起来有点奇怪 代码1: #include <stdio.h> typedef unsigned long uint32; typedef unsigned short uint16; typedef signed short sint16; sint16 rawTCU = -100; int main() { uint32 _tm
#include <stdio.h>
typedef unsigned long uint32;
typedef unsigned short uint16;
typedef signed short sint16;
sint16 rawTCU = -100;
int main()
{
uint32 _tmpSig = 0;
_tmpSig = (uint32)rawTCU;
printf("_tmpSig = %d",_tmpSig );
return 0;
}
代码2打印
_tmpSig = 65436
我不明白它的行为如何不同,为什么不同的类型会导致不同的值输出。为什么将uint16用于赋值时会创建不同的值(等于65536-100=65436)。这是如何得到优化的,而不是在使用uint32的过程中。请提供您的建议如何工作。谢谢 当有符号整数类型的负对象被分配(或强制转换)到大小较大的无符号整数类型时,符号位被传播 在这个表达式中
_tmpSig = (uint32)rawTCU;
_tmpSig = (uint16)rawTCU;
rawTCU负值的符号位传播到所有32位
在这个表达式中
_tmpSig = (uint32)rawTCU;
_tmpSig = (uint16)rawTCU;
存在到16位的截断。强制转换的结果被视为无符号值。所以这两种传播都没有发生
注意这个电话
printf("_tmpSig = %d",_tmpSig );
具有未定义的行为。你必须写作
printf("_tmpSig = %lu",_tmpSig );
^^^
这里缺少的是由于向
printf
传递参数时应用的整数提升规则而导致的隐式类型转换
您可能已经注意到,您可以使用相同的格式字符串打印char
、short int
或long int
。这是因为printf
的所有可选参数都经过默认参数升级。事实上,所有变量函数的参数都是如此
促销规则的简化总结如下:
- 花车变成双倍
- 小于int的整数类型(即chars和short int)变为int
- 无符号整数保持为无符号整数
_tmpSig = (uint32)rawTCU;
这里,由于我们正在从有符号类型转换,因此执行符号扩展,因此\u tmpSig
成为非常大的无符号数,这是-100
的表示形式
现在,当调用printf
时,不会发生升级,因为它已经是无符号int
。打印时,由于使用了“%d”格式,它将被重新解释为带符号的int,并产生-100
案例2:
_tmpSig = (uint16)rawTCU;
在此之后,\u tmpSig
现在保存一个无符号短int。此处不需要符号扩展名,因为它被转换为相同大小的类型。因此,代表性根本没有变化
但是,当传递到printf()
时,它将升级为带符号的int
。
因此这里有一个从无符号短
到有符号长
的隐藏转换。因为我们正在从无符号类型转换,所以这里没有符号扩展!这就是值实际变为65436的位置。现在,当打印为“%d”时,将打印相同的值
编辑:修复了@EricPostpischil指出的事实错误。如果您的编译器支持它,请使用from
,而不是自己编写。此外,在第一个代码段中,tmpSig是32(或64)位无符号长。%d”
格式用于有符号的int
(可能是32位)。这是一个不匹配的格式说明符和参数类型,这会导致未定义的行为。C标准根据涉及的值定义到无符号类型的转换。C实现不会在补码或符号和幅度实现中通过符号扩展进行转换(目前比较深奥)。C标准根据涉及的值定义到无符号类型的转换,而不是符号扩展。C实现不会在补码或符号和幅度实现中通过符号扩展进行转换(目前是深奥的)。Re“打印时,由于使用了“%d”格式,它会转换回带符号的int”:否,不会转换回int
。根据C标准,标准未定义使用%d
进行格式化时传递无符号int
的行为。当一个实现继续进行时,通常会发生的情况是无符号int
的位被重新解释为int
@ericppostschil True,而不是转换为int
。但是我试图解释OP所看到的行为,并且必须假设一个特定的平台。这里采用的许多隐式假设,例如short小于int,可能并不适用于每个C语言实现。关键是调用printf()
时发生的整数提升,我觉得没有其他答案。@EricPostChil关于你对“%d”的评论,我同意。我将看看是否可以重新表述这一部分,使其更加准确。