![](/img/trans.png)
[英]Why does printf print random value with float and integer format specifier
[英]Why format specifier %d or %i does not work for a double variable but %f works and print a float output of an integer variable?
我們必須始終使用%f
到 printf 一個%d
值,並%lf
接受scanf
的輸入嗎? 為什么格式說明符%d
或%i
不適用於double
精度變量,但%f
有效並打印 integer 變量的浮點 output? 聲明 double 並使用%lf
和printf
作為%f
輸入scanf
總是安全的嗎?
我的代碼:
int main(void)
{
double dnum = 7777;
printf(" %f \n", dnum);
return 0;
}
output 為 7777.000000
int main(void)
{
double dnum = 7777;
printf(" %i \n", dnum);
return 0;
}
Output 為 0
int main(void)
{
double dnum = 7777;
printf(" %d \n", dnum);
return 0;
}
Output 為 0
printf()
中的格式和數據不匹配調用未定義行為。
在您的代碼中,dnum 的類型是double
而不管其實際值如何,可能是dnum
。
%f
可用於打印double
,但不能使用%d
和%i
。
如果要打印double
,則應使用%g
、 %f
或%e
,具體取決於您希望打印的格式。
%d
與%i
相同(對於printf
),它與signed integer
一起使用。
歡迎來到未定義行為的世界!
使用%d
轉換說明符來打印double
值或使用%f
轉換說明符來打印int
值會調用未定義的行為。
%f
還意味着打印double
類型的值,而不是float
。 傳遞的float
會自動提升。
C 標准規定:
如果轉換規范無效,則行為未定義。288)如果任何參數不是相應轉換規范的正確類型,則行為未定義。
資料來源:C18,7.21.6.1/9
d,i -
int
參數轉換為樣式 [-]dddd 的有符號十進制。 精度指定出現的最小位數; 如果要轉換的值可以用更少的數字表示,則用前導零擴展它。 默認精度為 1。精度為零的零值轉換的結果是沒有字符。……
f,F - 表示浮點數的
double
精度參數轉換為樣式 [-]ddd.ddd 中的十進制表示法,其中小數點字符后的位數等於精度規范。 如果精度缺失,則取6; 如果精度為零且未指定標志,則不出現小數點字符。 如果出現小數點字符,則在其前面至少出現一位數字。 該值四舍五入到適當的位數。表示無窮大的雙參數被轉換為樣式[-]infor[-]infinity 之一——該樣式是實現定義的。 表示 NaN 的雙參數被轉換為樣式之一 [-]nanor[-]nan(n-char-sequence) — 哪種樣式和任何 n-char-sequence 的含義是實現定義的。 F 轉換說明符分別生成 INF、INFINITY 或 NAN,而不是 inf、infinity 或 nan。283)
資料來源:C18,§7.21.6.1/8
除了第一個示例,您得到的 output 是任意值(除非實現未指定其他情況)。 它不會以一種方式或另一種方式“工作”。
格式說明符: %d
或%i
需要帶signed int
參數,如果在格式化的printf()
語句中給出了其他任何內容,例如:
float f = 1.50235F;
printf("%d", f);
期望有signed int
,如果你傳遞一個float
或一個double
,它會傾向於未定義的行為並可能打印0
。
在更實際的意義上,如果你想自己動手,你可以添加-Wformat
標志並在命令提示符或任何命令 shell 中運行命令:
$ gcc -o main main.cpp -Wformat
然后您將收到編譯器生成的類似於以下內容的警告:
main.c: In function 'int main()':
main.c:9:14: warning: format '%d' expects argument of type 'int', but argument 2 has type 'double' [-Wformat=]
9 | printf("%d\n", d);
| ~^ ~
| | |
| int double
| %f
double
的精度是float
的兩倍(即double
有 15 個十進制數字的精度,而float
只有 7 個。因此,在這種情況下, %f
類型說明符也可以用於double
。)
要進一步了解格式說明符: C 中所有格式說明符的列表。
所有轉換說明符都期望它們對應的參數是特定類型; 不能隨意混搭。 %d
和%i
期望它們對應的參數具有int
類型 - 如果不是,則行為未定義,並且您(通常)會得到奇怪的 output。 整數和浮點值具有非常不同的二進制表示形式並且可能具有不同的大小 - 大多數現代平台使用 32 位存儲 integer 值和 64 位存儲雙精度值,這會影響這些值在printf
代碼中的解釋方式。
有關轉換說明符的權威列表及其所采用的 arguments 類型,請參閱C 2011 在線草案,第 7.21.6.1 節( fprintf
函數)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.