![](/img/trans.png)
[英]uint8_t rollover in Python? What is the best or most elegant way?
[英]uint8_t not rollover to 0 after reaching 255 not working properly
我是C-Headers的新手 - stdint.h
和inttypes.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
)。
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.