我正试图找出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_startva_arg和不要忘记va_end是编译器特有的。你不能把他们从别的地方带走,指望他们工作。如果你是一个编译器工程师,你最好按照手册的一页来使用它们,并且只试着理解它们的内部工作原理。
P.S:哦,他们的定义通常是非常神秘的,使用微妙的技巧来让它工作。
P.S2:回答您的问题_builtin_va_arg是在哪里定义的:编译器知道它,即所谓的内置函数。您可以在编译器的源代码中找到它;)

10-04 14:25