[英]function return changed as directly written in printf statement
#include <stdio.h>
#include <math.h>
int main() {
printf("%d\n", pow(3546, 0));
return 0;
}
上面的代碼打印值0
雖然下面的代碼打印值1
#include <stdio.h>
#include <math.h>
int main() {
int a = pow(3546, 0);
printf("%d\n", a);
return 0;
}
為什么會這樣? 盡管它們是等價的。
沒有等價的。 后者 function 在打印之前將數字顯式轉換為int
,而前者通過嘗試使用錯誤的格式說明符打印浮點數導致 UB - 你很幸運得到0
,你可能得到了一個任意數字。
請打開編譯器上的所有警告,它應該抱怨對錯誤類型的數據使用錯誤的格式。
pow
返回double
類型的結果,並且%d
不是用於格式化它的正確轉換說明符。 C 標准未定義由此產生的行為。
要打印double
,您可以使用%g
或%f
以及其他選項:
printf("%g\n", pow(3456, 0));
printf("%f\n", pow(3456, 0));
在int a = pow(3546,0);
, double
值會自動轉換為int
以初始化int
a
,然后用%d
打印該int
是正確的。
正如這個答案中提到的, printf
使用格式說明符來知道要從堆棧中彈出什么( %d
是sizeof(int)
,在我的系統中是 4 個字節)。
(編輯:正如rici在評論中指出的那樣,它不能保證是堆棧(在x86
上,它大部分時間都在 CPU 寄存器中)。標准從不談論實現,這就是這個問題的全部。)
一個有趣的小事實:在我的 Windows 10 框中,它是 0 和 1。在我的 Xubuntu VBox 中,它是 1 和 -2132712864。 因此, printf
僅彈出 4 個字節,而您的機器的字節序正在破壞結果。 來自pow(3) 手冊:
#include <math.h>
double pow(double x, double y);
float powf(float x, float y);
long double powl(long double x, long double y);
因此,為了在這兩種情況下獲得正確的結果,請使用正確的printf
格式說明符:
double a = pow(3546, 0);
和:
printf("%lf\n", pow(3546, 0));
如果您想了解有關可變參數函數的更多信息(例如printf
,它采用可變數量的參數),請從閱讀API 手冊頁開始。
#include <stdarg.h>
void va_start(va_list ap, last);
type va_arg(va_list ap, type);
void va_end(va_list ap);
void va_copy(va_list dest, va_list src);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.