[英]How does integer promotion work on C Cast?
我被一個意想不到的整數促銷所困擾,讓我感到奇怪。 在編譯器中是否一致是否在顯式轉換之前進行促銷?
讓我解釋。 有一個有符號的8位變量,如
int8_t s8a = -128; //<-- 0x80
分配給無符號16作為uint16_t s16b = s8a + 1;
我希望升級到一個更大的整數0xFF81
然后分配,這是一個常見的事故,並考慮在像MISRA C這樣的文件上。但是以uint16_t s16b = (uint16_t)s8a
的方式明確地轉換為無符號類型我本來期望s8a
立即失去其“簽名”,然后零擴展到16位,以給出0x0080
但實際上相反的情況發生,因為它得到符號擴展然后失去其簽名時,鑄造和分配給0xFF80
。
這種行為標准還是C的另一種未定義行為?
這與整數提升無關,但與類型轉換無關。 在您的情況下,該過程由C11標准很好地定義- 6.3.1.3有符號和無符號整數(p2) :
..如果新類型是無符號的,則通過重復加或減一個可以在新類型中表示的最大值來轉換該值,直到該值在新類型的范圍內。
所以這里0xFF80 = 0xFFFF + (-128) + 1
,因為0xFFFF
是可以在uint16_t
表示的uint16_t
。
給定初始化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
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.