如何在c++中处理var_arg上的多种类型?

问题描述 投票:0回答:1

怎么办?

代码导致:空指针取消引用。

10-08 17:26:00.835 5249 5617 D 摘要生成器:/apex/com.android.runtime/lib/bionic/libc.so!libc.so (strstr+) ()

10-08 17:26:00.835 5249 5617 D DigestGenerator: XXbase.apk!libtest.so (test_bool(char const*)+) ()

bool test_bool(const char *filename) {
    if (strstr(filename, "yes")) {
        return true;
    }
    return false;
}

long *test_long(long number, ...) {
    va_list args;
    va_start(args, number);
    for(int i=0; i<number; ++i) {
        if (test_bool(va_arg(args, const char *))) {
            //do something
            return 0;
        }
    }
    va_end(args);
    //do something
    return 0;
}

test_long(0, 1, "yes", 3);
c++ variadic-functions
1个回答
0
投票

C 风格的可变参数不携带任何类型信息。 在尝试读取参数之前,您的函数必须知道其中有哪些参数。 例如,

printf
使用格式字符串来确定存在什么类型的参数。 你可以做类似的事情,即

long test_long(std::string_view types, ...)
{
    va_list args;
    va_start(args, types);
    for (char c : types) {
        if (c == 'l') {
            long l = va_arg(args, long);
            // do something with l
        } else if (c == 's') {
            const char* s = va_arg(args, const char*);
            // do something with s
        } else {
            // unknown type
            return 0;
        }
    }
    return 1;
}

int main()
{
    test_long("llsl", 0, 1, "yes", 3);
}

演示

但这相当脆弱,您必须显式处理每种可能的类型。


一种更具 C++ 风格的方法是使用可变参数模板而不是 C 风格的

va_arg
。 例如:

template <typename... Args>
long test_long(Args... args)
{
    bool results[] = { test_bool(args)... };
    // do something with the results
    return 1;
}

int main()
{
    test_long(0, 1, "yes", 3);
}

演示

这可能有点复杂,只是因为 C++ 模板很复杂,但它比 C 风格的方法类型安全得多,因为参数的类型不会丢失。

在嵌入式上下文中,这可能会增加代码大小,因为每组不同的参数类型都会导致从模板实例化一个单独的函数。

© www.soinside.com 2019 - 2024. All rights reserved.