Атрибут Mingw64-w64 (формат) и заголовок <cinttypes> - PullRequest
0 голосов
/ 19 января 2019

У меня серьезные проблемы с правильной работой cinttypes на mingw64-w64 при кросс-компиляции.Я объяснил это минимальным (ish) примером, который запускается в 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

Результат выполнения, который дает:

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 Ответ

0 голосов
/ 19 января 2019

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. Ссылка на документацию


В моей системе (g ++ 8.2.1) использование %lld и т. Д. На самом деле работает правильно даже без первой строки, поэтому я подозреваю, что они, возможно, починили его для использования ISO stdio вместо MS stdio по умолчанию. Или, возможно, теперь MS stdio знает о %lld.

Возможно, стоит сообщить об ошибке, чтобы указать, что __attribute__((format(printf должен автоматически работать должным образом в зависимости от используемого stdio, без необходимости выполнять этот обходной путь.

...