动态创建va_list

use*_*251 16 c++ qt variadic-functions

我有一个功能

void foo(int cnt, va_list ap);
Run Code Online (Sandbox Code Playgroud)

我需要使用它,但要求非常严格,数量各va_list不相同,并且在运行期间会发生变化.我想做的是:

创建一个va_list(期望的char*)表单

QList<Contact*>
Run Code Online (Sandbox Code Playgroud)

哪里Contact是定义的类

class Contact
{
   public:
      QString getName();
   private: 
      QString m_name;

}; 
Run Code Online (Sandbox Code Playgroud)

我想在循环中填充va_list例如:

for (int idx = 0; idx<contacts.count(); idx++)
{
    contacts.at(idx)->getName(); // this i would like to pass to va_list

}
Run Code Online (Sandbox Code Playgroud)

有没有人知道我怎么能做到这一点?

slo*_*low 7

...嗯...也许不便携...肯定不好...但可以解决你的问题...

  • va_list(至少对于 Visual C++)只是 char* 的 #define
  • → 参数不需要在堆栈上
  • → 参数只需要在内存中连续即可
  • → 无需使用汇编程序和/或复制(请参阅我的“只是为了好玩的答案”:-)
  • → 无需担心清理问题
  • 高效的!
  • 在 w2k3 sp2 32 位 + vc++ 2010 上测试

#include <stdarg.h>
#include <string>
#include <vector>
#include <iostream>

#define N 6 // test argument count

void foo(int n, va_list args);

int main(int, char*[])
{
    std::vector<std::wstring> strings;
    std::wstring s(L"a");
    int i(0);

    // create unique strings...
    for (; i != N; ++i)
    {
        strings.push_back(s);
        ++s.front();
    }
    foo(N, reinterpret_cast<va_list>(strings.data()));
    return 0;
}

void foo(int n, va_list args)
{
    int i(0);

    for (; i != n; ++i)
        std::wcout << va_arg(args, std::wstring) << std::endl;
}


Joe*_*ley 6

你想要做的是模拟调用堆栈,这样你就可以将构造的va_list传递给foo().这是编译器特有的(并且警告,甚至32位和64位编译器之间也存在差异).以下代码仅供娱乐使用!!! as(如果它甚至适用于您的系统)它很容易破损.有了它,我使用一个平坦的内存缓冲区,并用一个计数和一堆字符串填充它.你可以用适当的指针填充它,然后将它们交给你.

它似乎适用于我的系统,Windows 7 w/Visual Studio 2008,仅适用于32位应用程序.

*不好的想法代码!*

#define PSEUDOSTACKSIZE ( sizeof(int) + 999 * sizeof(const char*) )
#pragma pack( push,1 )
union PSEUDOSTACK
{
    int count;
    char data[PSEUDOSTACKSIZE];
};
#pragma pack( pop )

void foo( int count, va_list args )
{
    for ( int i = 0; i < count; i++ )
    {
        char *s = va_arg( args, char* );
        printf( "%s\n", s);
    }
}

void bar( PSEUDOSTACK data, ... ) 
{ 
    va_list args; 
    va_start(args, data.count); 
    foo( data.count, args);
    va_end(args); 
} 
// And later on, the actual test case code.
PSEUDOSTACK barData;
barData.count = 999;
char *p = barData.data + sizeof(int);
for ( int i = 0; i < 999; i++, p += sizeof(char*) )
{
    *reinterpret_cast<char**>(p) = "ThisIsABadIdea";
}
bar( barData );
Run Code Online (Sandbox Code Playgroud)

我现在会因为想到这样的想法而垂头丧气.


Did*_*set 1

如果列表中的元素数量有限,我会根据元素数量进行手动调度。

void call_foo(int count, ...) {
    va_list args;
    va_start(args, count);
    foo(count, args);
    va_end(args);
}

switch (contacts.count()) {
    case 0: return call_foo(contacts.count());
    case 1: return call_foo(contacts.count(),
                            contacts.at(0)->getName());
    case 2: return call_foo(contacts.count(),
                            contacts.at(0)->getName(),
                            contacts.at(1)->getName());
    case 3: return call_foo(contacts.count(),
                            contacts.at(0)->getName(),
                            contacts.at(1)->getName(),
                            contacts.at(2)->getName());
    default: /* ERROR HERE, ADD MORE CASES */ return call_foo(0);
}
Run Code Online (Sandbox Code Playgroud)