代码之家  ›  专栏  ›  技术社区  ›  Robert Fraser

mingw64-w64 attribute(format)and<cinttypes>header

  •  1
  • Robert Fraser  · 技术社区  · 6 年前

    交叉编译时,我很难让cinttypes在mingw64-w64上正常工作。我把它归结为一个在Docker中运行的最小(ish)示例。

    inttypes测试.cpp

    #include <cstdio>
    #include <cstddef>
    #include <cstdint>
    #include <cinttypes>
    #include <cstdarg>
    
    __attribute__((format(printf, 1, 2))) static void myPrintf(const char* fmt, ...)
    {
        va_list args;
        va_start(args, fmt);
        vprintf(fmt, args);
        va_end(args);
    }
    
    int main(int argc, const char** argv)
    {
        int i32 = 5;
        int64_t i64 = 10;
        uint64_t u64 = 20;
        myPrintf("Testing int: %" PRId32 ", int64 = %" PRId64 ", size_t = %" PRIu64 "\n", i32, i64, u64);
        return 0;
    }
    

    文档文件

    FROM ubuntu:18.04
    RUN apt-get update -y && \
        apt-get install -y g++-mingw-w64-x86-64 && \
        apt-get clean && \
        rm -rf /var/lib/apt/lists/*
    ADD inttypes_test.cpp /inttypes-test/
    RUN cd "/inttypes-test" && \
        /usr/bin/x86_64-w64-mingw32-g++ -Wall -Werror -c inttypes_test.cpp
    

    运行的结果给出:

    inttypes_test.cpp: In function 'int main(int, const char**)':
    inttypes_test.cpp:20:100: error: unknown conversion type character 'l' in format [-Werror=format=]
         myPrintf("Testing int: %" PRId32 ", int64 = %" PRId64 ", size_t = %" PRIu64 "\n", i32, i64, u64);
                                                                                                        ^
    inttypes_test.cpp:20:100: error: unknown conversion type character 'l' in format [-Werror=format=]
    inttypes_test.cpp:20:100: error: too many arguments for format [-Werror=format-extra-args]
    

    所以,我认为 <cinttypes> 标题是针对这些平台的特定差异进行的论文。我做错什么了吗?

    1 回复  |  直到 6 年前
        1
  •  1
  •   M.M    6 年前

    inttypes 是一条红鲱鱼,你会得到同样的警告 myPrintf("%lld", 1LL); . 它警告使用 ll ,它在程序中由inttypes宏(正确)传递。

    这是旧版本的mingw的遗留问题,其中printf格式是通过未处理的msvcrt重定向的。 %lld ,因此警告是适当的。


    您可以通过向文件添加新的首行(在任何标准包括之前)来解决此问题:

    #define __USE_MINGW_ANSI_STDIO 1
    

    然后使用以下属性:

    __attribute__((format(__MINGW_PRINTF_FORMAT, 1, 2))) 
    static void myPrintf(const char* fmt, ...)
    

    这指示mingw-w64使用自己的printf实现,该实现符合ISO标准,并且 -Wformat 警告相应匹配。 Link to documentation


    在我的系统(G++8.2.1)上使用 %LLD 实际上,即使没有第一行,也能正确地执行操作,因此我怀疑他们可能已经修复了默认情况下使用i so stdio而不是ms stdio的问题。或者是Stdio女士现在知道了 %LLD .

    也许值得一份bug报告指出 __attribute__((format(printf 应该根据使用的stdio自动正常工作,而不必做这种变通。