问题描述
int max(int n, ...)
我使用 CDECL
调用约定,通常是主叫被叫方返回后清理变量。
I am using cdecl
calling convention where the caller cleans up the variable after the callee returns.
我想知道怎么做宏 va_end用来
,的va_start
和的va_arg
工作
I am interested in knowing how do the macros va_end
, va_start
and va_arg
work?
是否呼叫者传递的参数数组作为第二个参数为最大的地址?
Does the caller pass in the address of the array of arguments as the second argument to max?
推荐答案
如果你看看C语言存储在堆栈上参数的方法,方式的宏的工作应该很清楚: -
If you look at the way the C language stores the parameters on the stack, the way the macros work should become clear:-
Higher memory address Last parameter
Penultimate parameter
....
Second parameter
Lower memory address First parameter
StackPointer -> Return address
(注意,根据不同的硬件上的堆栈指针说不定一行向下和更高和更低的可以被交换)
(note, depending on the hardware the stack pointer maybe one line down and the higher and lower may be swapped)
的参数总是存储这样的,即使没有 ...
参数类型。
The arguments are always stored like this, even without the ...
parameter type.
的的va_start
宏只是建立一个指向第一个功能参数,例如: -
The va_start
macro just sets up a pointer to the first function parameter, e.g.:-
void func (int a, ...)
{
// va_start
char *p = (char *) &a + sizeof a;
}
这使得 P
指向第二个参数。在的va_arg
宏做到这一点: -
which makes p
point to the second parameter. The va_arg
macro does this:-
void func (int a, ...)
{
// va_start
char *p = (char *) &a + sizeof a;
// va_arg
int i1 = *((int *)p);
p += sizeof (int);
// va_arg
int i2 = *((int *)p);
p += sizeof (int);
// va_arg
long i2 = *((long *)p);
p += sizeof (long);
}
的 va_end用来
宏刚 P
值设置为 NULL
。
注:
- 优化编译器和寄存器,而不是使用堆栈一些RISC CPU的存储参数。在
...
参数presence会关掉这个能力和编译器使用堆栈。
- Optimising compilers and some RISC CPUs store parameters in registers rather than use the stack. The presence of the
...
parameter would switch off this ability and for the compiler to use the stack.
这篇关于如何可变参数在gcc中实现?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!