2016-03-17 77 views
-6
#include<conio.h> 
#include<stdio.h> 

main() 
{ 
    printf("%d %f ", 4.0, 4.0); 
    getch(); 
} 

我得到的輸出爲0 4.000000。我想知道準確的原因。C中的格式說明符

+6

不正確的格式說明的使用是一個未定義的行爲。你可以得到任何結果,這取決於編譯器/ c標準庫的實現。 – Ari0nhh

+0

使用'conio.h'和missing來指定'main'的返回值似乎表明您正在使用歷史前的C編譯器。對於所有現代化平臺的現代化標準來說,都有很好的開源編譯器,你應該明確地轉向其中的一種。 –

+0

另一個'解釋UB對我'的問題。 DCV :. '我想知道準確的原因'AKA'我的教授/助教要我寫出準確的理由':( –

回答

2

主要的原因是因爲你正在使用錯誤的格式說明...

當你這樣做:

printf("%d %f ",4.0,4.0f); 

你告訴你的編譯器,你要打印的整數float,您需要傳遞2個浮點數,所以編譯器不會將浮點數轉換爲int

do instad

printf("%d %f ",(int)4.0,4.0f); 

多個參考關於格式說明..

通常的可變型顯示

%C炭單個字符

%d(%I)INT有符號整數

%E(%E)浮動或雙指數格式

%F浮子

%LF雙

%克(%G)float或雙用途%f或%e按要求

%o int unsigne d八進制值

%的對指針地址存儲在指針字符炭序列的

%S陣列

%U詮釋無符號十進制

%×( %X)int無符號十六進制值

+1

'%f'爲'double','float'在傳遞給可變參數函數printf時轉換爲'double' '。'%lf'與'%f'相同,'l'被忽略。'%p'需要'void *'指針。 – chqrlie

+0

編譯器是否應該隱式地將4.0轉換爲int? –

+0

@Claudio Cortese不,編譯器不需要隱式地將「4.0」轉換爲「int」,C規範特別指出這種格式/參數的不匹配是未定義行爲(UB),編譯器_could_執行一次演員(我知道沒有人會這麼做)。許多編譯器會檢查問題併發出警告。 – chux

0

printf函數不知道可變參數列表中需要的數據類型,除非您告訴它有什麼。這就是格式說明符的數據類型部分。

發生了什麼事情你告訴它,第一個參數是一個int,但你給它一個不同的數據類型。結果是未定義的。

如果您想查看printf正在做的事情的類型,請閱讀variadic functions in C。這會給你一個更好的想法,爲什麼它對於函數期望的類型非常重要,因爲它與你給的類型相同。

爲了提供從我剛纔提供的鏈接採取了代碼示例:

#include <stdio.h> 
#include <stdarg.h> 

void simple_printf(const char* fmt, ...) 
{ 
    va_list args; 
    va_start(args, fmt); 

    while (*fmt != '\0') { 
     if (*fmt == 'd') { 
      int i = va_arg(args, int); 
      printf("%d\n", i); 
     } else if (*fmt == 'c') { 
      // note automatic conversion to integral type 
      int c = va_arg(args, int); 
      printf("%c\n", c); 
     } else if (*fmt == 'f') { 
      double d = va_arg(args, double); 
      printf("%f\n", d); 
     } 
     ++fmt; 
    } 

    va_end(args); 
} 

int main(void) 
{ 
    simple_printf("dcff", 3, 'a', 1.999, 42.5); 
}