Mingw64-w64属性(格式)和< cinttypes>标头 [英] Mingw64-w64 attribute(format) and <cinttypes> header
问题描述
在交叉编译时,让cinttypes在mingw64-w64上正常工作时,我遇到了很大的麻烦.我将其简化为一个在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);返回0;}
Dockerfile
从FROM版本:18.04运行apt-get update -y&&\apt-get install -y g ++-mingw-w64-x86-64&&\易于清洁\rm -rf/var/lib/apt/lists/*添加inttypes_test.cpp/inttypes-test/运行cd"/inttypes-test"&&\/usr/bin/x86_64-w64-mingw32-g ++ -Wall -Werror -c inttypes_test.cpp
运行结果给出:
inttypes_test.cpp:在函数'int main(int,const char **)'中:inttypes_test.cpp:20:100:错误:格式为[-Werror = format =]的未知转换类型字符"l"myPrintf("Testing int:%" PRId32,int64 =%" PRId64,size_t =%" PRIu64"\ n",i32,i64,u64);^inttypes_test.cpp:20:100:错误:格式为[-Werror = format =]的未知转换类型字符"l"inttypes_test.cpp:20:100:错误:格式[-Werror = format-extra-args]的参数过多
因此,我有点假设< cinttypes>
标头的全部要点在于解决这些平台特定的差异.我在做错什么吗?
inttypes
是一个红色鲱鱼,您从 myPrintf(%lld",1LL);
.它会警告使用 ll
,它在程序中(正确)是由inttypes宏提供的.
这是来自较旧版本的MinGW的宿醉,在该版本中,通过MSVCRT重定向了printf格式,该格式无法处理%lld
,因此应该发出警告.
您可以通过在文件中添加新的顶行来解决此问题(在包含任何标准之前):
#define __USE_MINGW_ANSI_STDIO 1
,然后使用以下属性:
__ attribute __((format(__ MINGW_PRINTF_FORMAT,1,2)))静态无效myPrintf(const char * fmt,...)
这指示mingw-w64使用其自己的符合ISO标准的printf实现,并相应地匹配 -Wformat
警告.链接到文档
在我的系统(g ++ 8.2.1)上,即使没有第一行,使用%lld
等实际上也可以正确运行,因此我怀疑他们可能已将其修复为使用ISO stdio而不是MS默认情况下为stdio.也许MS stdio现在知道%lld
.
值得指出一个错误报告,指出 __ attribute __((format(printf
>
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?
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.
这篇关于Mingw64-w64属性(格式)和< cinttypes>标头的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!