关于C++变长参数的一些细节

存在仅含变长参数的函数吗?
当然可以,至少编译器不会报错。你可以像这样定义一个仅含变长参数的函数:

void foo(...)
{
    //...
}

不过这样的函数基本上没什么用,主要原因是你无法取出它的参数。C++通过宏va_start以及va_arg从函数的变长参数列表中取值,其中va_start用以定位变长参数列表的起始地址,这需要借助于参数列表中最后一个固定参数:

var bar(int firstArg, ...)
{
    va_list pArgs;
    va_start(pArgs, firstArg);
    int nextArg = va_arg(pArgs, int);
}

当然,由于函数的参数都在栈中,因此也许有些十分诡异的手段可以直接从栈里将参数抠出来,不过这些用法太高端,我也不懂。

 
用于定位的固定参数可以是引用吗?
答案是不行。下面这两个函数:

void foo1(int a, int b, int c)
{
    cout << &a << &b << &c << endl;
}

void foo1(int& a, int b, int c)
{
    cout << &a << &b << &c << endl;
}

foo1的输出是(你的机器也许和我不一样)0x003cfce4, 0x003cfce8, 0x003cfcec
foo2的输出以及 0x0042fa24, 0x0042f948, 0x0042f94c

也就是说,如果你用来定位的,参数列表中的最后一个固定参数,是个引用:

void foo(int a, int &b, ...)
{
    va_list pArgs;
    va_start(pArgs, b);
    //...
}

int omg = 0;
foo(123, omg, 321);

那么实际上你并不能取得变长参数的其实地址,比如上面这个函数,你取到的地址实际上是(&omg + sizeof(omg))。

发表评论

电子邮件地址不会被公开。 必填项已用*标注