这是让我感到沮丧的原因:
我们有两个整数:一个是int16_t
类型,另一个是int8_t
。我已经将这两个变量初始化如下:
int8_t short_int = 250 //This equals -6, and its binary representation is 0b1111 1010
到目前为止一切顺利。
int16_t my_int = short_int //as we already know short_int is 0b1111 1010
对我来说,my_int应该等于0b1111 1010对吧?作为16bit整数的值 0b1111 1010的十进制表示为250.好的,但它没有。
打印my_int的值我得到-6,二进制表示为0b1111 1111 1111 1010 与short_int
完全不同作为二进制。
答案 0 :(得分:15)
int8_t short_int = 250
会导致实现定义的行为。 int8_t
的范围是-128
到127
。
显然,您的实现会在此为-6
生成值short_int
。好到目前为止。
但是现在您必须记住C具有保值转换。如果您将-6
转换为任何其他有符号整数类型,则无论其位代表是什么,它仍将是-6
。
有些人会谈论“符号扩展”和其他类似的东西,但是为了理解C的工作方式,你只需要记住,除非超出类型的范围,否则值将被保留;在这种情况下,它被截断(对于无符号类型)或实现定义的行为(对于有符号的类型;通常是2的补码截断)。
答案 1 :(得分:13)
C基于值而不是位模式。
如果您将int8_t
分配给int16_t
,则两者之后都具有相同的值。
对于负值,这意味着它们具有不同的位模式(假设负值的公共表示)。
请注意,您的int8_t
实际上是否定的。
答案 2 :(得分:2)
使用:
int16_t my_int = (uint8_t) short_int;
而不是:
int16_t my_int = short_int;
short_int
是一个负的有符号整数,因此在转换为int16_t
时会经历符号扩展。
答案 3 :(得分:0)
标准说
typedef
名称intN_t
指定宽度为N
的有符号整数类型,无填充位和二进制补码表示。因此,int8_t
表示宽度精确为signed integer
位的8
类型。
将short_int
分配给my_int
时,其二进制表示的位数会增加,同时保留short_int
符号和值(称为"符号扩展")。
short_int
为负数,因此my_int
将具有相同的值,但具有相同的值,但带有一些填充位。
答案 4 :(得分:0)
ungur_gongor的回答是正确的。如果您确实想要访问位模式,就好像它是int8_t
或int16_t
一样,您可以使用union
:
union {
int8_t short_int;
int16_t my_int;
} converter;
converter.my_int = 0;
converter.short_int = 250;
printf("%d\n", converter.my_int);
请注意对齐(int8_t
的填充位置?)和int16_t
的字节顺序。
这会保留位模式(而不是值),尽管可能仅在覆盖short_int
的字节上(这就是为什么我先将my_int
设置为0)。