2012-07-04 28 views
4

我得到了gcc編譯器的警告,如果下面的代碼被執行,程序中止我無法得到原因?如果有人澄清它會很有幫助。c中的va_arg函數中的可變參數類型

#include<stdio.h> 
#include<stdarg.h> 
int f(char c,...); 
int main() 
{ 
    char c=97,d=98; 
    f(c,d); 
    return 0; 
} 

int f(char c,...) 
{ 
    va_list li; 
    va_start(li,c); 
    char d=va_arg(li,char); 
    printf("%c\n",d); 
    va_end(li); 
} 

GCC告訴我:

warning: 'char’ is promoted to ‘int’ when passed through ‘...’ [enabled by default] 
note: (so you should pass ‘int’ not ‘char’ to ‘va_arg’) 
note: if this code is reached, the program will abort 

回答

10

參數傳遞給可變參數的功能進行默認參數提升;任何小於int(例如char)的任何東西首先轉換爲int(並且float轉換爲double)。

所以va_arg(li,char)永遠不會是正確的;改爲使用va_arg(li,int)

+1

爲什麼在k&r書中沒有提及? – Dhatri

+0

@vindhya:我不知道。 –

+0

有趣的是,一些編譯器有'va_arg()',如果你使用'char'的話,它將會取整到'int'。 Microsoft Visual Studio 2005的'va_arg()'具有以下內容:'#define _crt_va_arg(ap,t)(*(t *)((ap + = _INTSIZEOF(t)) - _INTSIZEOF(t)))'with (sizeof(n)+ sizeof(int)-1)&〜(sizeof(int)-1)的額外的宏定義'#define _INTSIZEOF –

1

是的,這似乎是C標準中的一個怪癖。但是,看起來這只是與va_arg()有關。

您可以查看printf()的各種實現,以瞭解如何解決此問題。例如,one in klibc很容易閱讀。