使用不同编译器的 C++ 和可变参数

标签 c++ gcc clang variadic-functions

我正在尝试将用 GCC 编写的 C++ 项目重新编译为 clang,但它给我带来了 varargs 方法的一些问题。

NB:该项目还应该使用不符合 c++-11 的编译器进行编译,因此我不能在这里使用花哨的 C++11 语法..

GCC 在没有警告的情况下接受以下代码 (1):

void Set(TreeIter &it, ...) {
    va_list va;
    va_start(va, it);
    gtk_list_store_set_valist(*this, const_cast<TreeIter *>(&it), va);
    va_end(va);
}

和(2):

void AddTail(...) {
    TreeIter it;
    gtk_list_store_append(*this, &it);
    va_list va;
    va_start(va, this);
    gtk_list_store_set_valist(*this, &it, va);
    va_end(va);
}

虽然 CLANG 对两者发出警告:

(1):

 ./ootree.h:444:30: warning: 'va_start' has undefined behavior with reference types [-Wvarargs]

(2):

 ./ootree.h:476:30: warning: second parameter of 'va_start' not last named argument [-Wvarargs]

我可以通过用拷贝替换 TreeIter 引用来轻松修复(1)(并且标准似乎要求我这样做),但我没有找到修复(2)的简单方法,这是一个最小的方法显示行为的独立示例,该程序不仅适用于 gcc,还适用于 clang,但这些警告非常可怕......

#include <stdio.h>
#include <stdarg.h>

struct T {
    void print(...) {
        va_list va;
        va_start(va, this);
        vprintf("%d %d %d\n", va);
        va_end(va);
    }
};

int main() {
    T().print(2, 4, 6);
}

最佳答案

(2) 的解决方案是显式采用前 2 个参数,可能提供 1 个参数重载:

void AddTail(gint column, GValue *value, ...) {
    TreeIter it;
    gtk_list_store_append(*this, &it);
    gtk_list_store_set_value(*this, &it, column, value);
    va_list va;
    va_start(va, value);
    gtk_list_store_set_valist(*this, &it, va);
    va_end(va);
}

void AddTail(gint column) {
    TreeIter it;
    gtk_list_store_append(*this, &it);
    assert(column == -1);
}

关于使用不同编译器的 C++ 和可变参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34069843/

相关文章:

c++ - 重载运算符=,读取字符串错误

c++ - 返回类型取决于模板参数

c - GCC 和 G++ struct packing 的区别?

c - 地址 sanitizer 和 __attribute(section ("mysection")) 失败

multithreading - 无法将参数传递给 std::thread?

c++ - clang 中的 constexpr 错误,但 gcc 中没有?

c++ - 直接 3D 影响数据类型 double

c++ - 带有头文件的纯函数文件总是导致 undefined reference

gcc - 当 --sysroot 指向另一个目录时,如何让 FFmpeg 找到已安装的库?

c - 为什么 GCC 以不同方式存储全局和静态 int?