[英]Unsigned int in C behaves negative
我不明白為什么對於以下代碼,無符號int的輸出為負。 就像一個簽名的int一樣。
uint32_t yyy=1<<31;
printf("%d\n",yyy);
輸出為:
-2147483648
這是-2^31
。
%d
的格式說明符期望一個int
,而不是一個unsigned int
,因此代碼具有未定義的行為。 根據C99標准第7.19.6.1節,fprintf函數 :
如果任何參數都不是相應轉換規范的正確類型,則行為未定義。
將%u
用作unsigned int
:
uint32_t yyy=1u<<31;
printf("%u\n",yyy);
輸出:
2147483648
這是因為您的printf參數(如%d)正在將您的數字隱式轉換為int。
請改用%u。
使用%u
輸出無符號數字:
printf("%u\n", yyy);
正如許多人所說,使用%u
標識符。
這樣做的原因是, printf
無法判斷任何額外參數的類型(它們以va_list
形式給出),因此程序員必須使用格式字符串提供該信息。 當您隨后提供%d
, printf
將調用此命令:
int val;
val = va_arg(va_list, int);
並將您的unsigned int隱式轉換為有符號。
您需要使用unsigned int
格式說明符:
printf("%u\n",yyy);
^^
對於printf
使用錯誤的格式說明符是未定義的行為,這在C99草案標准第7.19.6.1
節中進行了介紹7.19.6.1
函數 ,其中還涉及關於格式說明符的printf
,它說:
如果轉換規范無效,則行為未定義。 248)如果任何參數都不是對應轉換規范的正確類型,則行為未定義。
printf
的cppreference頁面有一個漂亮的表,用於指定可用的格式說明符。
因為您將其打印為已簽名。 請改用%u
。
printf
采用可變數量的參數。 當您調用它時,編譯器會盡職地將它們全部放入堆棧中。 因為它是C,所以沒有反射printf
隨后無法推斷收到的東西的類型。 在位級別上,您不能從表面上區分無符號整數或浮點數,合適的較小結構,較大結構的一部分等形式的有符號整數。
這就是為什么您還必須提供格式字符串的原因。 它告訴printf
從堆棧讀取什么類型以及以什么順序讀取。 它完全取決於該格式字符串,無法對其進行驗證。
因此,按照已經發布的單行答案,如果您告訴它將字段解釋為簽名數量,則它將被打印為簽名數量。
整數以二進制補碼格式存儲。 這意味着僅通過查看值就無法判斷該數字是帶符號的還是無符號的。 您必須告訴機器要使用哪種表示形式,並自己對其進行跟蹤。
在您的示例中,您告訴機器jjj
是無符號的(用於類型檢查),然后通過在格式字符串中使用%d
來要求printf()
將其視為已簽名(無法獲得類型信息)。 如果要打印無符號整數,請使用%u
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.