2010-04-19 31 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