簡體   English   中英

如何確認C中無符號長整數的范圍?

[英]How can I confirm the range of unsigned long integer in C?

unsigned long在我的Linux gcc上有8個字節。

unsigned long long在我的Linux gcc上也有8個字節。

所以我認為它們可以顯示的整數范圍是從0分鍾到最大(2 ^ 64-1)

現在我想確認一下我是否正確。

這是我的代碼

#include <stdio.h>
int main(void)
{
    printf("long takes up %d bytes:\n", sizeof(long));
    printf("long long takes up %d bytes:\n", sizeof(long long));

    unsigned long a = 18446744073709551615;
    a++;
    printf("a + 1 = %lu\n", a); 

    unsigned long long b = 18446744073709551615;
    b++;
    printf("b + 1 = %llu\n", b); 

    return 0;
}

但是,代碼無法編譯,我收到以下警告:

warning: integer constant is so large that it is unsigned

我哪里做錯了? 我該如何修改代碼?

當初始化NUM,您可以附加“UL”unsigned longULLunsigned long long

例如:

unsigned long a = 18446744073709551615UL;
unsigned long long b = 18446744073709551615ULL;

此外,使用%zu而不是%d因為sizeof返回size_t

根據cppreference

  • 整數后綴(如果提供)可能包含以下一項或兩項(如果提供了兩者,則它們可以按任何順序出現:
    • unsigned-suffix (字符u或字符U
    • long-suffix (字符l或字符L )或long-long-suffix (字符序列ll或字符序列LL )(自C99起)

C標准5.2.4.2.1整數類型的大小<limits.h>

1下面給出的值應替換為適用於#if預處理指令的常量表達式。 此外,除了CHAR_BITMB_LEN_MAX ,以下內容應替換為與根據整數提升轉換的對應類型的對象的表達式具有相同類型的表達式。 它們的實現定義值的大小(絕對值)應等於或大於顯示的值,並帶有相同的符號。

用-1初始化無符號數。 這將自動為C中的MAX值。

#include <stdio.h>
int main(void)
{
    printf("long takes up %d bytes:\n", sizeof(long));
    printf("long long takes up %d bytes:\n", sizeof(long long));

    unsigned long a = -1;
    printf("a = %lu\n", a); 

    unsigned long long b = -1;
    printf("b = %llu\n", b); 

    return 0;
}

更新 :根據評論更改代碼:)

您可以在<limits.h>找到一些有用的定義。

如何確認C中無符號長整數的范圍?

最好 ,只需使用<limits.h>的宏。 它更好地自我記錄代碼的意圖。

unsigned long long b_max = ULLONG_MAX;

或者,將-1指定給無符號類型。 由於-1不在無符號類型的范圍內,它將通過添加該類型的MAX值加1來轉換為目標類型。即使在具有填充的稀有機器上也能工作。

...如果新類型是無符號的,則通過重復加或減一個可以在新類型中表示的最大值來轉換該值,直到該值在新類型的范圍內。 C11dr§6.3.1.32

對於無符號類型,最小值當然為0。

unsigned long long b_min = 0;
unsigned long long b_max = -1;
printf("unsigned long long range [%llu %llu]\n", b_min, b_max); 

請注意,挑剔的編譯器會抱怨使用b_max = -1;分配超出范圍的值b_max = -1; 使用ULLONG_MAX


我哪里做錯了?

警告“警告:整數常量太大而無符號”是由於18446744073709551615是平台上long long范圍之外的整數十進制常量。 簡單的十進制常量僅限於此。 附加Uu 然后編譯器會考慮unsigned long long

unsigned long long b = 18446744073709551615u;

此外,沒有C規范說18446744073709551615是unsigned long long的最大值。 至少必須如此。 它可能更大。 因此,指定b = 18446744073709551615u可能不會分配最大值

我該如何修改代碼?

如上所示

正如rsp所述,您可以使用ULULL指定文字的類型。 但這不會導致您的算法代碼產生確鑿的結果。

您的打印值始終為0因為

2^64 % 64 = 0 // 64 = 8 byte
2^64 % 32 = 0 // 32 = 4 byte
2^64 % 16 = 0 // 16 = 2 byte

正如你所看到的,變量大小總是加倍,所以如果我們使用8個字節的包裝數,它只會在較小的大小上包含多個類型並產生相同的結果。

sizeof將顯示正確的值。

但通常你想在代碼中檢查這些東西,而不是在輸出上檢查,所以你可以按照Arndt Jonasson的建議使用limits.h

或者您可以在編譯時使用static_assert進行檢查。

暫無
暫無

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

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