代码之家  ›  专栏  ›  技术社区  ›  Arpegius

如何获取vau arg的地址?

  •  1
  • Arpegius  · 技术社区  · 14 年前

    我破解了一些旧的C API,得到了一个编译错误,代码如下:

    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* ,所以我不希望分配额外的内存。

    3 回复  |  直到 14 年前
        1
  •  2
  •   Community CDub    7 年前

    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
        }
    

    阿洛卡() 通常是盲目的快速,因为它通常是使用相同的机制,用于分配局部变量的空间来实现的。当调用函数退出时,空间将自动释放。

        2
  •  2
  •   Johannes Schaub - litb    14 年前

    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
    }
    

    你不能得到可变参数的地址。

        3
  •  0
  •   tomlogic    14 年前

    char * 堆栈上参数的地址。由于某些平台在寄存器中传递参数,并且由于堆栈对齐问题,因此您实际上不想执行以下操作:

    如果这是针对单个平台的,您可以查看它的stdarg.h并编写一个解决方案来获得堆栈上参数的地址。

    不过,这不是个好主意。