[英]Why is this code printing 0?
void main()
{
clrscr();
float f = 3.3;
/* In printf() I intentionaly put %d format specifier to see
what type of output I may get */
printf("value of variable a is: %d", f);
getch();
}
實際上, %d
告訴printf
在某個位置查找整數參數。 但是你傳遞了一個float
參數,它被放在不同的地方。 C 標准沒有指定執行此操作時會發生什么。 在這種情況下,可能在printf
尋找整數參數的地方有一個零,所以它打印了“0”。 在其他情況下,可能會發生不同的事情。
對printf
使用無效的格式說明符會調用未定義的行為。 這在C 標准的第 7.21.6.1p9 節中指定:
如果轉換規范無效,則行為未定義。282) 如果任何參數不是相應轉換規范的正確類型,則行為未定義。
這意味着您無法可靠地預測程序的輸出結果。 例如,我系統上的相同代碼打印 -1554224520 作為值。
至於最有可能發生的情況, %d
格式說明符正在尋找一個int
作為參數。 假設一個int
被堆棧和一個通過int
是4個字節長,則printf
功能着眼於堆棧中給出的值上的下一個4個字節。 許多實現不會在堆棧上傳遞浮點值,而是在寄存器中傳遞,因此它會看到碰巧在那里的任何垃圾值。 即使在堆棧上傳遞float
, float
和int
具有非常不同的表示形式,因此將float
的字節打印為int
很可能不會為您提供相同的值。
讓我們看一個不同的例子。 假設我寫
#include <string.h>
char buf[10];
float f = 3.3;
memset(buf, 'x', f);
memset
的第三個參數應該是一個整數(實際上是一個size_t
類型的值),告訴memset
要將多少個buf
字符設置為'x'
。 但是我傳遞了一個float
值。 發生什么了? 好吧,編譯器知道第三個參數應該是一個整數,所以它會自動執行適當的轉換,代碼最終將buf
的前三個(三個點零)字符設置為'x'
。
(重要的是,編譯器知道memset
的第三個參數應該是整數的方式是基於memset
的原型函數聲明,它是頭文件<string.h>
。)
現在,當你打電話
printf("value of variable f is: %d", f);
你可能認為同樣的事情會發生。 您傳遞了一個float
,但%d
需要一個int
,因此會發生自動轉換,對嗎?
錯誤的。 讓我再說一遍:錯了。
也許令人驚訝的事實是, printf
是不同的。 printf
很特別。 編譯器不一定知道傳遞給printf
的參數的正確類型應該是什么,因為這取決於隱藏在格式字符串中的%
說明符的詳細信息。 所以沒有自動轉換到正確的類型。 您的工作是確保您實際傳遞的參數類型完全適合格式說明符。 如果它們不匹配,編譯器不會自動執行相應的轉換。 如果它們不匹配,就會發生瘋狂的錯誤結果。
( printf
的原型函數聲明是什么樣的?字面上看起來像這樣: extern int printf(const char *, ...);
。這三個點...
表示可變長度參數列表或“varargs”,它們告訴編譯器它不知道還有多少參數,或者它們的類型應該是什么。所以編譯器執行一些基本的轉換——比如將類型char
和short int
上轉換為int
,並將float
為double
——然后就這樣了。)
我說“編譯器不一定知道傳遞給printf
的參數的正確類型應該是什么”,但是現在,好的編譯器會加倍努力並嘗試弄清楚,如果可以的話。 他們仍然不會執行自動轉換(根據語言規則,他們實際上不被允許這樣做),但他們至少可以警告您。 例如,我在兩個不同的編譯器下嘗試了您的代碼。 兩者都說了一些warning: format specifies type 'int' but the argument has type 'float'
。 如果您的編譯器沒有給您這樣的警告,我鼓勵您查明是否可以啟用這些警告,或者考慮切換到更好的編譯器。
嘗試
printf("... %f",f);
這就是您打印浮點數的方式。 也許您只想打印f 的x 位數字,例如:
printf("... %.3f" f);
這將在點后打印 3 位數字的浮點數。 請通讀此列表:
%c - 字符
%d 或 %i - 有符號十進制整數
%e - 使用 e 字符的科學記數法(尾數/指數)
%E - 使用 E 字符的科學記數法(尾數/指數)
%f - 十進制浮點數
%g - 使用 %e 或 %f 中的較短者
%G - 使用 %E 或 %f 中的較短者
%o - 有符號八進制
%s - 字符串
%u - 無符號十進制整數
%x - 無符號十六進制整數
%X - 無符號十六進制整數(大寫字母)
%p - 指針地址
%n - 未打印任何內容
代碼打印 0,因為您使用的是格式標記 %d,它表示有符號十進制整數 ( http://devdocs.io )。
你能試試嗎
void main() {
clrscr();
float f=3.3;
/* In printf() I intentionaly put %d format specifier to see what type of output I may get */
printf("value of variable a is: %f",f);
getch();
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.