我被一个意外的整数提升所咬住,使我感到奇怪。 是否在显式强制转换之前进行升级是否在整个编译器中一致?
让我解释一下。具有签名的8位变量,例如
int8_t s8a = -128; //<-- 0x80
将一个未签名的16分配为uint16_t s16b = s8a + 1;
,我希望将其提升为更大的整数0xFF81
,然后再分配,这是一个普遍的事故,在MISRA C等文档中都可以使用。我希望uint16_t s16b = (uint16_t)s8a
会立即失去其“符号”,然后零扩展到16位以得到s8a
,但实际上却相反,因为它当强制转换并赋予0x0080
时,符号扩展的 then 会失去其签名。
这是行为标准还是C的另一个未定义行为?
答案 0 :(得分:4)
这与整数提升无关,但与类型转换有关。在您的情况下,该过程由C11 Standard - 6.3.1.3 Signed and unsigned integers (p2)进行了很好的定义:
..如果新类型是无符号的,则该值将通过重复转换 比最大值增加或减去一个以上 以新类型表示,直到值在新范围内 类型。
这里0xFF80 = 0xFFFF + (-128) + 1
,因为0xFFFF
是uint16_t
中可以表示的最大值。
答案 1 :(得分:1)
给出初始化int8_t s8a = -128;
:
uint16_t s16b = s8a + 1;
:
s8a + 1
中,s8a
((int8_t)-128
)中的值被提升为(int)-128
,并与(int)1
相加得到(int)-127
。uint16_t s16b = (int)-127;
中,(int)-127
被转换为(uint16_t)0xff81
并存储在s16b
中。uint16_t s16b = (uint16_t)s8a + 1;
:
(uint16_t)s8a
中,s8a
((int8_t)-128
)中的值将转换为(uint16_t)0xff80
。(uint16_t)0xff80 + 1
中:
INT_MAX >= 65535
,则(uint16_t)0xff80
转换为(int)0xff80
并与(int)1
相加得到(int)0xff81
。INT_MAX < 65535
,则1
转换为(uint16_t)1
并与(uint16_t)0xff80
相加得到(uint16_t)0xff81
。uint16_t s16b = (int)0xff81;
中(当INT_MAX >= 65535
时)或在初始化uint16_t s16b = (uint16_t)0xff81;
中(当INT_MAX < 65535
时):
INT_MAX >= 65535
,则(int)0xff81
会转换为(uint16_t)0xff81
并存储在s16b
中。INT_MAX < 65535
,则(uint16_t)0xff81
存储在s16b
中。在两种情况下,s16b
都被初始化为值(uint16_t)0xff81
。