簡體   English   中英

uint16_t和uint32_t之間的差異

[英]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==32uint32_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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM