2010-04-19 32 views
1

我砍了一些舊的C API和我有下面的代碼編譯錯誤:如何獲取va_arg的地址?

void OP_Exec(OP* op , ...) 
{ 
    int i; 
    va_list vl; 
    va_start(vl,op); 
    for(i = 0; i < op->param_count; ++i) 
    { 
     switch(op->param_type[i]) 
     { 
      case OP_PCHAR: 
       op->param_buffer[i] = va_arg(vl,char*); // ok it works 
      break; 
      case OP_INT: 
       op->param_buffer[i] = &va_arg(vl,int); // error here 
      break; 
      // ... more here 
     } 
    } 
    op->pexec(op); 
    va_end(vl); 
} 

gcc version 4.4.1 (Ubuntu 4.4.1-4ubuntu9) 錯誤是:

main.c|55|error: lvalue required as unary ‘&’ operand 

那麼到底爲什麼它是不可能在這裏得到一個指向參數?

如何解決?此代碼通常以不同的OP*執行,所以我寧願不分配額外的內存。

只知道參數的大小就可以遍歷va_list嗎?

+0

va_arg是一個宏,你不能把它的地址。 – 2010-04-19 21:20:26

回答

1

由於litb's answer是不可用的你,因爲你不能修改pexec()功能,你能解決這個使用alloca()如果你的編譯器提供了它:經常

switch(op->param_type[i]) 
    { 
     int *itmp; 

     case OP_PCHAR: 
      op->param_buffer[i] = va_arg(vl,char*); // ok it works 
     break; 

     case OP_INT: 
      itmp = alloca(sizeof(int)); 
      *itmp = va_arg(vl, int); 
      op->param_buffer[i] = itmp; 
     break; 
     // ... more here 
    } 

alloca()通常是瞬息萬變的,因爲它使用與用於爲局部變量分配空間的機制相同的機制來實現。當調用函數退出時,空間將自動釋放。

+0

Thx,它很好。我檢查拆解後的代碼,它與我完美接合。我使用了更緊湊的代碼'*((int *)(op-> param_buffer [i] = alloca(sizeof(int))))= va_arg(vl,int);'。 – Arpegius 2010-04-20 08:36:46

+1

如果你把它分成兩行,那麼對未來的維護者來說會更容易一些:'op-> param_buffer [i] = alloca(sizeof(int)); *(int *)op-> param_buffer [i] = va_arg(vl,int);' – caf 2010-04-20 09:10:30

2

變化param_buffer是的

struct ValueUnion { 
    Type type; 
    union { 
    char *stringval; 
    int intval; 
    } u; 
}; 

一個數組,那麼你可以說

op->param_buffer[i].type = op->param_type[i]; 
switch(op->param_type[i]) 
{ 
    case OP_PCHAR: 
     op->param_buffer[i].u.stringval = va_arg(vl,char*); // ok it works 
    break; 
    case OP_INT: 
     op->param_buffer[i].u.intval = va_arg(vl,int); // ok it works 
    break; 
    // ... more here 
} 

你不能得到一個可變參數arg的地址。

+0

OK thx,它可能會工作,但我從動態庫加載op-> pexec,我現在不能重寫其他模塊。 – Arpegius 2010-04-19 21:12:05

0

它不可移植,但在某些實現中,va_list是堆棧上參數地址的char *。由於某些平臺在寄存器中傳遞參數,並且由於堆棧對齊問題,因此您不需要執行以下操作:

如果這是針對單個平臺,您可以查看它的stdarg.h並破解一個解決方案來獲取堆棧上參數的地址。

雖然主要破解,並不是一個好主意。

+0

我相信所有可變長度參數總是在堆棧上傳遞,而不是在寄存器中傳遞。 – nategoose 2010-04-21 16:07:53