2016-02-17 49 views
4

代碼:的printf redifines UINT32_MAX

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

int main(int argc, char *argv[]) { 
    printf("%lu\n%lu\n%lu\n%lu\n%lu\n%lu\n%lu\n", 
     UINT32_MAX, 
     UINT32_MAX, 
     UINT32_MAX, 
     UINT32_MAX, 
     UINT32_MAX, 
     UINT32_MAX, 
     UINT32_MAX); 
    return 0; 
} 

輸出:

4294967295 
4294967295 
4294967295 
4294967295 
4294967295 
18446744073709551615 
18446744073709551615 

錯誤或故意的嗎?爲什麼? 我認爲它自己說話,但接口需要我添加更多的行之前,我可以發佈它(以大量代碼爲少文本lol)

+1

你'printf'格式不匹配你的價值觀通過。你的編譯器應該已經警告過這個。因爲你傳遞了意外的參數類型,所以它們被'printf'錯誤地解壓縮。 –

+1

如果您使用的是GCC或Clang,在編譯'-Wall -Wextra'時添加這些標記是一種很好的做法。讓這成爲一種習慣。 – jweyrich

回答

14

您正在使用%lu,這是不正確的。 %lu說明符僅適用於unsigned long只有unsigned long而不是uint32_t。這就是輸出不正確的原因。改爲使用PRIu32

如果您在編譯時啓用了警告,您的編譯器應該爲您抓到此錯誤。

#include <stdio.h> 
#include <stdint.h> 
#include <inttypes.h> // defines PRIu32 

printf(
    "%" PRIu32 "\n" 
    "%" PRIu32 "\n" 
    "%" PRIu32 "\n" 
    "%" PRIu32 "\n" 
    "%" PRIu32 "\n" 
    "%" PRIu32 "\n" 
    "%" PRIu32 "\n", 
    UINT32_MAX, 
    UINT32_MAX, 
    UINT32_MAX, 
    UINT32_MAX, 
    UINT32_MAX, 
    UINT32_MAX, 
    UINT32_MAX); 

在實踐中,PRIu32被定義爲"u"在大多數系統。

+1

另一種方法是繼續使用'%lu',並使用'(unsigned long)UINT32_MAX'。如果您出於某種原因不能使用'',這可能會很有用。 –

+1

@Ian Abbott需要添加:鑄造到'(無符號長整型)'是一個很好的選擇,因爲'unsigned long'是'uint32_t'的最小寬度。 – chux

1
$ gcc -Wall -Wextra your_code.c 
warning: format ‘%lu’ expects type ‘long unsigned int’, but argument 2 has type ‘unsigned int’ 

這不是一個long,不要使用l符。

你的代碼有未定義行爲,實際上它基本上讀取garabage。

+0

它不是'unsigned long',但它也不是'unsigned int',所以僅僅省略'l'是不正確的。 –

+0

是的,從技術上來說'int'的最小尺寸是2個字節。找到這樣一個系統可能會很棘手;) –

+0

@IanAbbott(回覆自己) - 但是,我_think_常量的類型'UINT32_MAX'將始終是'unsigned int'或'unsigned long'中的一個,而不是其中的一個。 ,所以'%u'或'%lu'中的一個可以工作,但問題是知道哪一個。因此需要來自''的'PRIu32'宏。 –

3

這是未定義的行爲:您通過unsigned int,但您的%lu格式告訴printf您正在通過long unsigned int。這導致undefined behavior,因爲printf通過格式說明符所說(事實上,它沒有其他方式來找出,因爲類型信息不傳遞到printf)。

一旦你解決您的格式有問題,問題消失:

printf("%u\n%u\n%u\n%u\n%u\n%u\n%u\n", 
    UINT32_MAX, 
    UINT32_MAX, 
    UINT32_MAX, 
    UINT32_MAX, 
    UINT32_MAX, 
    UINT32_MAX, 
    UINT32_MAX); 

這將打印

4294967295 
4294967295 
4294967295 
4294967295 
4294967295 
4294967295 
4294967295 

Demo.

+0

這使得在OP的系統中'uint32_t'和'unsigned'是合理的假設相同的類型。一般來說,這不是一個便攜式解決方案。 – chux