[英]Diff between uint16_t and uint32_t
在我的代碼中,uint16_t和uint32_t之間沒有區別。 為什么?
我在帶有ARMv7(32位)的RasPi上使用Raspbian。
root@zentrale:/src# uname -a
Linux zentrale 4.19.42-v7+ #1219 SMP Tue May 14 21:20:58 BST 2019 armv7l GNU/Linux
這是代碼:
void main()
{
uint16_t wert1;
uint32_t wert2;
int i;
wert1=2;
wert2=2;
for (i=0; i<33;i++)
{
printf("i: %2d\tLShifted wert1: %10u\t",i,wert1 << i);
printf("RShifted wert1: %10u\t",wert1 >> i);
printf("LShifted wert2: %10u\t",wert2 << i);
printf("RShifted wert2: %10u\n",wert2 >> i);
}
exit(0);
}
這是剝離的輸出:
i: 0 LShifted wert1: 2 RShifted wert1: 2 LShifted wert2: 2 RShifted wert2: 2
i: 1 LShifted wert1: 4 RShifted wert1: 1 LShifted wert2: 4 RShifted wert2: 1
[...]
i: 14 LShifted wert1: 32768 RShifted wert1: 0 LShifted wert2: 32768 RShifted wert2: 0
i: 15 LShifted wert1: 65536 RShifted wert1: 0 LShifted wert2: 65536 RShifted wert2: 0
i: 16 LShifted wert1: 131072 RShifted wert1: 0 LShifted wert2: 131072 RShifted wert2: 0
[...]
我原本以為wert1是16位,i = 15的值變為零,因為名稱告訴它是16位長。
相反,這兩個變量沒有區別。
我在Raspian中找到了uint16_t最大值的參考(參見https://raspberry-projects.com/pi/programming-in-c/memory/variables )
那么為什么沒有區別呢?
非常感謝!
兩個操作數<<
將進行整數提升 ,即C11 6.3.11p2 :
2可以在任何可以使用int或unsigned int的表達式中使用以下內容:
- 具有整數類型(int或unsigned int除外)的對象或表達式,其整數轉換等級小於或等於int和unsigned int的等級。
- _Bool,int,signed int或unsigned int類型的位字段。
如果
int
可以表示原始類型的所有值(由寬度限制,對於位字段),則該值將轉換為int
; 否則,它將轉換為unsigned int
。
由於您平台上的int
是32位寬,因此uint16_t
所有值都可由int
表示。 uint32_t
轉換為unsigned int
!
現在兩者的行為看起來都是平等的, 因為 GCC保證了大部分內容! GCC支持的所有體系結構的所有簽名算法都使用2的補碼; 和另外GCC不考慮行為<<
上為未定義在符號位改變的情況下簽署的數字 。
但是,如果移位寬度大於或等於操作數的寬度(在本例中為32位),則仍然未定義(即使在GCC中)會發生什么,因此<< 32
和<< 33
將具有未定義的行為。
除此之外,一般來說,C標准表示如果左移位正有符號整數,則行為未定義,以使符號位發生變化! 當你將uint16_t
向左移動這么多位以改變int
的移位時會發生這種情況。 因此,
(uint16_t)0xFFFF << 16
在32位平台上有未定義的行為,因為最高位被移位到int
的符號位,而
(uint32_t)0xFFFF << 16
沒有,因為后者會使用無符號算術。 與往常一樣,編譯器可以定義超出標准要求的行為。
由於Integer Promotions沒有區別
你應該真正閱讀關於主題隱式類型促銷規則的這篇優秀文章
假設4字節int
,在任何算術運算之前, uint16_t
被轉換為signed int
,然后執行該操作。
左數字的負數未定義。 但在這種情況下,這個數字不能是負數。 因此,您將獲得與uint32_t
相同的輸出
您應該對左移的輸出進行類型轉換以便正確操作。
此外,您正在運行循環,直到i<33
。 在i==32
, uint32_t
將有未定義的行為,在i==31
你將對uint16_t
有符號整數有未定義的行為
printf("i: %2d\tLShifted wert1: %10u\t",i, (uint16_t)(wert1 << i);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.