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

浪子不回头ぞ 提交于 2021-01-28 19:02:12

问题


I'm having serious trouble getting cinttypes to work properly on mingw64-w64 when cross-compiling. I've gotten it down to a minimal(ish) example that runs in docker.

inttypes_test.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;
}

Dockerfile

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

The result of running that gives:

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]

So, I kind of assumed the whole point of the <cinttypes> header was to paper over these platform-specific differences. Am I doing something wrong?


回答1:


inttypes is a red herring, you get the same warning from myPrintf("%lld", 1LL);. It warns about use of ll, which in your program is (correctly) delivered by the inttypes macro.

This is a hangover from older versions of MinGW where printf formatting was redirected via MSVCRT that didn't handle %lld, so it was appropriate to warn.


You can fix the problem by adding a new top line to the file (before any standard includes):

#define __USE_MINGW_ANSI_STDIO 1

and then using the following attribute:

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

This instructs mingw-w64 to use its own printf implementation which conforms to ISO standards, and to have -Wformat warnings match accordingly. Link to documentation


On my system (g++ 8.2.1) the use of %lld etc. actually behaves correctly even without the first line, so I suspect they may have fixed it to use ISO stdio instead of MS stdio by default. Or perhaps MS stdio now knows about %lld.

It may be worth a bug report to point out that __attribute__((format(printf ought to automatically work properly according to which stdio is in use, without you having to do this workaround.



来源:https://stackoverflow.com/questions/54265217/mingw64-w64-attributeformat-and-cinttypes-header

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!