如何在C中获取函数参数的指针?

时间:2011-01-20 18:39:08

标签: c dynamic macros arguments c-preprocessor

是否有一个泛型方法来获取C中每个参数的指针 你会用vararg函数吗?

特殊语法,如$ 1,$ 2,$ 3

如果没有,那么有一些预处理器宏定义了吗?

如果在C中不可能,我也对Objective C解决方案感兴趣。 我知道我可以使用_cmd special hidden来获取当前方法的选择器 参数。是否有某种_arg1,_arg2 ?? 也可以在_cmd之后直接指向内存吗?是吗 考虑参数指针的“安全”是彼此相邻的吗?

更新我自己的问题

如果我通过使用一些汇编代码访问帧堆栈,我可以得到一个保持 关于ebp的函数指针对吗?所以可以访问参数 一样的方法 ?很抱歉,如果这很明显,我对汇编程序了解不多。

5 个答案:

答案 0 :(得分:2)

不,你能做到这一点的唯一方法是使用stdarg.h

中提供的va_list

答案 1 :(得分:2)

在你的情况下可能但是可能不完全有用的是提取当前和先前的堆栈帧指针(即bp寄存器),并使用标准堆栈帧结构确定多少4字节(对于32位)应用程序)参数单元已在调用当前例程时传递。您将无法确定哪些单位为char,short或long,以及其中两个单元是否为long long / __ int64参数。


我已经考虑过这个了。考虑一个典型的函数调用“func(a,b)”。调用代码,除非你在寄存器中有参数(一些x86-32编译器选项和推荐用于x86-64的intel),代码将会像这样显示

               ; long *esp,*ebp;
push b         ; *(--esp)=b;
push a         ; *(--esp)=a;
call func      ; *(--esp)=return_address_location;
return_address_location:
add esp,8      ; esp+=2;    // free memory allocated for passing parameters

然后你来func处理

func:
push ebp       ; *(--esp)=(long) ebp;    // save current ebp <=> current stack frame 
mov ebp,esp    ; ebp=esp;                // create new stack frame in ebp
sub esp,16     ; esp-=4;                 // reserve space for local variables <=> sizeof(long)*4

(func code ...)

现在当你在func中并且你需要访问参数时,你用ebp + 2和ebp + 3来解决这些参数(* ebp包含以前的ebp,ebp + 1是返回地址。当你需要访问本地变量时他们使用ebp-4到ebp-1(如果它们不是全长并且你有一些包装选项可能会过度简化)。

经过一段时间func已完成它的事情,你需要返回:

mov esp,ebp    ; esp=ebp;         // unreserve space for local variables
pop ebp        ; ebp=*(esp++);    // restore previous ebp <=> previous stack frame
ret            ; eip=*(esp++);    // pop return address into instruction pointer

从第一个片段中,您还将看到在返回后如何立即释放第一个堆栈分配(用于传递参数)。

一些提示:

  • 为自己做数学计算 单步(指令 指令)通过电话/回程 顺序,你会得到如何的想法 解决原来的问题。这个 看起来是基本的堆栈处理 或多或少都一样 架构和实现如此 知道
  • 是件好事
  • 想象一下计算错误 memset / memcpy到本地缓冲区和 它将如何破坏数据 堆栈包括返回地址, 以前的堆栈帧等
  • 记下ds和ss中的值 (数据和堆栈选择器)和if 它们包含完全相同的值a 你的解决方案可以使用memcpy 将参数从堆栈复制到 数据存储器用于检查或 无论如何有帮助
  • 如果ds = ss,你可以使用&amp;找到了 来自的传递参数的地址 在func(&amp; param1,&amp; param2)
  • 如果ds和ss相等或不相同(因为它们 可能是多线程的 申请)你需要一个 memcpy变种,使用“远 解决“谁将处理 ds和ss不同的情况

答案 2 :(得分:0)

请参阅stdarg(3)tutorial

答案 3 :(得分:0)

不,没有特殊的方法可以做到这一点,或任何特殊的符号。

我想你可以定义一个宏来获取每个参数并生成一个指向它的指针(找到Boost预处理器库);我确定我不想。

int somefunc(int arg1, char *arg2)
{
    int *p_arg1 = &arg1;
    char **p_arg2 = &arg2;
    ...
}

答案 4 :(得分:0)

如果可变参数函数的所有参数都具有相同的类型(例如void *),则可以执行以下操作:

type nth_arg(va_list ap, size_t n)
{
    va_list ap2;
    va_copy(ap2, ap);
    while (n--) va_arg(ap2, type);
    return va_arg(ap2, type);
}

type替换为实际类型。