我正试图找出va_start(),va_arg()宏背后的原因。下面的代码运行良好。
#include <iostream>
#include <cstdarg>
void f(double a, double b, ...)
{
va_list arg;
va_start(arg, b);
double d;
while((d = va_arg(arg, double)) != 0)
{
std::cout << d << '\n';
}
}
int main(int argc, char *argv[])
{
f(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 0.0);
return 0;
}
如我所料,它给出了这样的结果:3 4 5 6 7 8 9。
然后我找到了宏的定义(在internet中,因为我的头stdarg.h是神秘的——它定义了宏vau arg(v,l)就像builtin vau arg(v,l),最后一个没有在它中定义,而stdarg.h不包含任何内容,所以它在某个库中吗??? )尽管如此,我还是代替了“cstdarg”写了:
typedef char* va_list;
#define _INTSIZEOF(n) \
((sizeof(n)+sizeof(int)-1) &~(sizeof(int)-1))
#define va_start(ap,v) \
(ap = (va_list)&v + _INTSIZEOF(v))
#define va_arg(ap,t) \
(*(t*)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)))
#define va_end(ap) (ap = (va_list)0)
输出变为wierd,例如1
-0.0409377
-0.0409377
4.88084e-270型
4.85706e-270型
一
二
三
四
五
六
七
八
九
我认为变量参数放在最后一个声明的参数旁边,但显然有更复杂的情况。如果有人揭发我错在哪里或者那里发生了什么,我会很高兴的。
最佳答案
va_start
、va_arg
和不要忘记va_end
是编译器特有的。你不能把他们从别的地方带走,指望他们工作。如果你是一个编译器工程师,你最好按照手册的一页来使用它们,并且只试着理解它们的内部工作原理。
P.S:哦,他们的定义通常是非常神秘的,使用微妙的技巧来让它工作。
P.S2:回答您的问题_builtin_va_arg
是在哪里定义的:编译器知道它,即所谓的内置函数。您可以在编译器的源代码中找到它;)