gcc 中如何实现可变参数? [英] How are variable arguments implemented in gcc?
问题描述
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?
调用者是否将参数数组的地址作为第二个参数传递给max?
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)
参数总是像这样存储1,即使没有 ...
参数类型.
The arguments are always stored like this1, 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
.
The va_end
macro just sets the p
value to NULL
.
注意:
- 优化编译器和一些 RISC CPU 将参数存储在寄存器中,而不是使用堆栈.
...
参数的存在将关闭此功能并让编译器使用堆栈.
- 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 中如何实现可变参数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!