簡體   English   中英

uint8_t在達到255不能正常工作后沒有翻轉到0

[英]uint8_t not rollover to 0 after reaching 255 not working properly

我是C-Headers的新手 - stdint.hinttypes.h 我正在嘗試一些代碼來了解uint8_t工作原理。 但是,它似乎遇到了一個問題。

我已經分別聲明了4個uint8_t整數,邊界值分別為0,255,256,-1,並對它進行了一些簡單的算術運算。 我這樣做是因為我想知道c-compiler(我在linux上使用gcc 5.4.0 )生成了什么錯誤/警告 如果沒有,我有興趣知道輸出的樣子。 下面給出的代碼。

#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>

int main() {
        int a = 10;
        printf("%d\n", a++);
        printf("%d\n\n", a);

        // 8 bit unsigned integer -> range[0, 255]
        uint8_t ua81=0, ua82=255, ua83=256, ua84=-1;
        printf("--------STDINT.H----uint8_t--DEMO--------\nua81 = %" PRIu8 "\n", ua81);
        printf("ua82 = %" PRIu8 "\nua83 = %" PRIu8 "\nua84 = %" PRIu8 "\n\n", ua82, ua83, ua84);
        printf("ua81+1 = %" PRIu8 "\nua82-3 = %" PRIu8 "\nua83-4+7 = %" PRIu8 "\nua84-1+20 = %" PRIu8 "\n----------\n\n", ua81+1, ua82-3, ua83-4+7, ua84-1+20);

        return 0;
}

此代碼的輸出如下:

vagrant@ubuntu-xenial:~/Documents/Coding Practice/p_c$ vi stdint_h.c
vagrant@ubuntu-xenial:~/Documents/Coding Practice/p_c$ gcc -Wall stdint_h.c -o a
stdint_h.c: In function ‘main’:
stdint_h.c:11:33: warning: large integer implicitly truncated to unsigned type [-Woverflow]
  uint8_t ua81=0, ua82=255, ua83=256, ua84=-1;
                                 ^
vagrant@ubuntu-xenial:~/Documents/Coding Practice/p_c$ ./a
10
11

--------STDINT.H----uint8_t--DEMO--------
ua81 = 0
ua82 = 255
ua83 = 0
ua84 = 255

ua81+1 = 1
ua82-3 = 252
ua83-4+7 = 3
ua84-1+20 = 274
----------

如前所述,我使用的是Linux機器,使用gcc 5.4.0編譯器。

vagrant@ubuntu-xenial:~/Documents/Coding Practice/p_c$ gcc --version
gcc (Ubuntu 5.4.0-6ubuntu1~16.04.11) 5.4.0 20160609
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

我無法理解為什么,對於變量ua84 ,該值在達到255后沒有ua84 0 ,而ua83也是ua83 我認為考慮到255之后的翻轉, ua84應該是18

我覺得這與編譯時生成的與變量ua83有關的warning中提到的Implicit Truncation有關。 我不知道到底出了什么問題。 我也想知道如何去做,我仍然想繼續使用uint8_t

由於隱式促銷, ua84-1+20將是一個int ,它將具有值274.您應該明確地將結果轉換為uint8_t以使其變為18。

printf根據格式(*)沒有足夠的魔法來轉換它的參數。 它只期望它接收它所需要的東西並且只提取傳遞的參數。 所以在這里你應該寫:

    printf("ua81+1 = %" PRIu8 "\nua82-3 = %" PRIu8 "\nua83-4+7 = %" PRIu8 "\nua84-1+20 = %"
            PRIu8 "\n----------\n\n", (uint8_t)(ua81+1), (uint8_t)(ua82-3), (uint8_t)(ua83-4+7),
            (uint8_t)(ua84-1+20));

(*)更確切地說,格式說明符存在問題。 在第7.21.6.1段中,針對C11的fprintf函數§7草案n1570說:

hh指定以下d,i,o,u,x或X轉換說明符適用於signed char或unsigned char參數(該參數將根據整數提升進行提升,但其值應轉換為signed char或打印前未簽名的字符 ); ...

所以,如果你明確地使用了%hhu ,你就會得到18(即使已經通過了274)。 但不幸的是,來自inttype.h的宏只需要正確顯示預期范圍的值,因此許多實現將PRIu8轉換為u (感謝Eric Postpischil注意到)。

表達式ua84-1+20使變量ua84經歷一個稱為整數提升的東西:它變成了一個int ,然后整個表達式求值為int

然后它被打印為unsigned int - 你可能會看到PRIu8被定義為"u" ,這當然需要unsigned int (並且即使傳遞了uint8_t因為變量函數如何提升其整數參數( uint8_t值)獲得提升為int ,然后通過printf() )將其視為unsigned int )。

詳細信息: https//en.cppreference.com/w/c/language/conversion

printf系列功能非常危險且不穩定,不存在類型安全性。 因此,如果您提供的參數不是您使用格式說明符指定的類型,則調用未定義的行為。 這就是圖書館的程序員會告訴你的。

表達式ua84-1+20導致對int 隱式類型提升 ,請參閱隱式類型提升規則 因此,您使用PRIu8對printf PRIu8 ,告訴它在傳遞int時期望uint8_t

它可以通過轉換回預期類型來修復: (uint8_t)(ua84-1+20) ,它將按預期打印18。

值得注意的是,像printf這樣的所有可變函數也有類似的隱式類型提升,稱為“默認參數提升”。 無論你做什么,這些實際上都會將參數轉換為int 但是庫期待促銷發生,所以當你鍵入PRIu8后跟(uint8_t)whatever ,他們都期望在內部處理(int)(uint8_t)whatever

然而,圖書館打印274 ,UB或不打印是非常可疑的。 這表明printf實現實際上並沒有在內部將參數轉換回uint8_t 庫如何證明這是一個很好的問題,因為我們可以看到它會導致錯誤和不那么粗糙的代碼。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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