2014-02-14 36 views
1

在我main功能,我使用下面的代碼傳遞持股量參數搞砸了價值

float f = 32.0; 
func("test string %f", f); 

func(這些都是例子名)聲明如下

void func(const char *str, ...); 

我在執行的這個函數,我使用一個叫做all_types的聯合來獲得傳遞的參數值

union all_types 
{ 
    void *v; 
    CLObject *obj; 
    char *s; 
    long l; 
    char c; 
    float f; 
    int i; 
    double d; 
}; 

,然後給出一個值,該聯盟這樣

union all_types *o = calloc(1, sizeof(union all_types)); 
while ((o->v = va_arg(list, void *)) != NULL) 

現在,當我知道這個說法是一個浮動,因爲這將是很奇怪的值(我設置斷點弄明白)。工會的il值將是32,因爲他們應該。但是,f的值是一些奇怪的數字,如0.00000000000000000000000000000000000000000013592595。有誰知道我爲什麼得到這種行爲?這個函數適用於我測試過的其他類型的對象。

回答

3

va_arg宏的第二個參數是實際參數的實際類型。由於調用va_arg而沒有發生轉換。如果你不知道實際論證的實際類型,那麼你就不好運,因爲沒有辦法找出答案。

請注意,默認參數轉換確實發生在通話本身,因此不可能收到floatcharunsigned short。 (該float將被轉換爲double和另外兩個intunsigned int,視)

這就是爲什麼printf格式讓你指定參數的類型,除了float

+0

什麼我基本上是在這個函數做的是試圖實現一種printf函數,並與printf的,我用的格式說明。通過使用與說明符相結合的聯合體,我可以將它與其他類型結合使用。 「float」是我唯一遇到過問題的人。 –

+0

@ChrisLoonam:你可能會很幸運。不習慣它。它不適用於別人的系統,別人的編譯器或下一版本的編譯器。 – rici

+0

@ChrisLoonam,所以你想要的是類似於http://stackoverflow.com/questions/5977326/call-printf-using-va-list –

3

你在做什麼所調用undefined behaviorvariadic functions將轉換花車和不確定的行爲,因爲無效*不兼容,所以你可以沒有期望以結果。我們可以通過轉到draft C99 standard部分7.15.1.1看到這種情況的在va_arg宏它說:

[...]如果沒有實際的一個參數,或者如果類型與實際的類型兼容下一個參數(根據默認參數促銷推廣),該行爲是不確定的,[...]

做的正確的方式,這將是:

o->d = va_arg(list, double) 

和你有格式說明所以這應該是可能的:

"test string %f" 
      ^^