簡體   English   中英

C:打印大號

[英]C : Printing big numbers

請考慮以下事項:

#include <stdio.h>

main() {
    unsigned long long verybig = 285212672;

    printf("Without variable : %llu\n", 285212672);
    printf("With variable    : %llu", verybig);
}

這是上述程序的輸出:

Without variable : 18035667472744448
With variable    : 285212672

從上面可以看到,當printf作為常量傳遞時,它會輸出一些巨大的錯誤數字,但是當該值首次存儲在變量中時, printf輸出正確的數字。

這背后的原因是什么?

試試285212672ULL ; 如果你在沒有后綴的情況下編寫它,你會發現編譯器將它視為常規整數。 它在變量中工作的原因是因為整數在賦值中被強制轉換為unsigned long long ,因此傳遞給printf()的值是正確的類型。

在你問之前,不,編譯器可能不夠智能,無法從printf()格式字符串中的"%llu ”中找出它。 這是一個不同的抽象層次。 編譯器負責語言語法, printf()語義不是語法的一部分,它是一個運行時庫函數(除了它包含在標准中之外,與你自己的函數沒有什么不同)。

對於32位int和64位unsigned long long系統,請考慮以下代碼:

#include <stdio.h>

int main (void) {
    printf ("%llu\n",1,2);
    printf ("%llu\n",1ULL,2);
    return 0;
}

哪個輸出:

8589934593
1

在第一種情況下,兩個32位整數1和2被壓入堆棧, printf()將其解釋為單個64位ULL值,2 x 2 32 + 1. 2參數無意中包含在ULL值。

在第二個中,您實際上是推送64位1值和多余的32位整數2 ,這將被忽略。

請注意,格式字符串與實際參數之間的“不合時宜”是一個壞主意。 就像是:

printf ("%llu %s %d\n", 0, "hello", 0);

可能會崩潰,因為%llu將消耗32位"hello"指針, %s將嘗試取消引用最后的0參數。 下面的“圖片”說明了這一點(我們假設單元格是32位,“hello”字符串存儲在0xbf000000。

What you pass     Stack frames     What printf() uses
                 +------------+
0                | 0          | \
                 +------------+  > 64-bit value for %llu.
"hello"          | 0xbf000000 | /
                 +------------+
0                | 0          |    value for %s (likely core dump here).
                 +------------+
                 | ?          |    value for %d (could be anything).
                 +------------+

值得指出的是,有些編譯器會針對這種情況提供有用的警告 - 例如,這就是GCC對您的代碼所說的內容:

x.c: In function ‘main’:
x.c:6: warning: format ‘%llu’ expects type ‘long long unsigned int’, but argument 2 has type ‘int’

285212672是一個int值。 printf期望一個unsigned long long ,你傳遞一個int 因此,它會從堆棧中獲取更多的字節,而不是傳遞實際值並打印垃圾。 當你將它放在一個unsigned long long變量中,然后將它傳遞給函數之前,它將在賦值行中被提升為unsigned long long ,並將該值傳遞給printf ,它正常工作。

數據類型只是一種解釋內存位置內容的方法。
在第一種情況下,常量值作為int存儲在只讀存儲器位置中,printf嘗試將該地址解釋為8字節位置,因為它被指示存儲的值在其打印垃圾值的過程中很長。
在第二種情況下,printf嘗試將長long值解釋為8個字節,並打印出預期的值。

暫無
暫無

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

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