2010-05-16 132 views
3

我要初始化指針參數的鏈接列表,像這樣:在va_arg使用指針

/* 
* Initialize a linked list using variadic arguments 
* Returns the number of structures initialized 
*/ 
int init_structures(struct structure *first, ...) 
{ 
    struct structure *s; 
    unsigned int count = 0; 
    va_list va; 
    va_start(va, first); 

    for (s = first; s != NULL; s = va_arg(va, (struct structure *))) { 
     if ((s = malloc(sizeof(struct structure))) == NULL) { 
      perror("malloc"); 
      exit(EXIT_FAILURE); 
     } 
     count++; 
    } 

    va_end(va); 

    return count; 
} 

的問題是,鐺錯誤type name requires a specifier or qualifierva_arg(va, (struct structure *)),並說該類型說明符默認爲int。它還注意到在(struct structure *)struct structure *處實例化的形式。這,似乎分配給s的是int (struct structure *)

它編譯罰款時,括號從(struct structure *)刪除,但都應該被初始化結構是無法訪問。

爲什麼int假設當括號裏傳遞給va_arg的類型參數?我怎樣才能解決這個問題?

回答

5

va_arg是許多系統上的一個宏,顯然圍繞struct structure *的括號會導致宏擴展,所以無法解析。所以不要這樣做。

這有沒有關係,你的初始結構是「人跡罕至」的原因。您正在分配結構並將它們分配到s,但s是一個局部變量。您不能通過分配給本地變量來影響調用者的值。爲了完成你想做的事,呼叫者需要傳遞一個指針到一個指針,然後你就可以初始化

int init_structures(struct structure **first, ...) 
{ 
    struct structure **s; 
    unsigned int count = 0; 
    va_list va; 
    va_start(va, first); 

    for (s = first; s != NULL; s = va_arg(va, struct structure **)) { 
     if ((*s = malloc(sizeof(struct structure))) == NULL) { 
      perror("malloc"); 
      exit(EXIT_FAILURE); 
     } 
     count++; 
    } 

    va_end(va); 

    return count; 
} 

,主叫方應該做的:

struct structure *a, *b; 
init_structures(&a, &b, NULL); 
+1

'va_arg'必須是一個宏。 – 2010-05-16 22:13:41

1

你不能把括號周圍型va_arg。你不需要。 va_arg是一個奇怪的野獸。實際上,這是一個CPP宏,可擴展成某種每編譯器的魔法。如果你看看你的編譯器的擴展,你會看到你的編譯器是如何實現的。不管它是什麼,它不喜歡parens。

4

第7.15節。 1.1 C99(該va_arg宏)要求:

參數類型應是這樣的類型 名稱SPECI音響編,使得類型 指向具有指定類型 的對象的指針可以簡單地通過將a *類型後綴 來獲取。

這就是爲什麼括號不在這裏不允許的。

其他回答已經解釋了爲什麼你需要通過struct structure **並將malloc結果賦值爲*s