如何在mingw-w64 gcc 7.1中无需警告地打印size_t?

我在nuwen.net上使用minGW的mingw-w64(x64)分支。 这是来自7.1版本的gcc:

gcc --version gcc (GCC) 7.1.0 

我正在编译这个程序:

 #include  int main(void) { size_t a = 100; printf("a=%lu\n",a); printf("a=%llu\n",a); printf("a=%zu\n",a); printf("a=%I64u\n",a); } 

有警告和c11标准:

 gcc -Wall -Wextra -Wpedantic -std=c11 test_size_t.c 

我收到这些警告:

  test_size_t.c: In function 'main': test_size_t.c:6:14: warning: format '%lu' expects argument of type 'long unsigned int', but argument 2 has type 'size_t {aka long long unsigned int}' [-Wformat=] printf("a=%lu\n",a); ~~^ %I64u test_size_t.c:6:14: warning: format '%lu' expects argument of type 'long unsigned int', but argument 2 has type 'size_t {aka long long unsigned int}' [-Wformat=] printf("a=%lu\n",a); ~~^ %I64u test_size_t.c:7:14: warning: unknown conversion type character 'l' in format [-Wformat=] printf("a=%llu\n",a); ^ test_size_t.c:7:9: warning: too many arguments for format [-Wformat-extra-args] printf("a=%llu\n",a); ^~~~~~~~~~ test_size_t.c:7:14: warning: unknown conversion type character 'l' in format [-Wformat=] printf("a=%llu\n",a); ^ test_size_t.c:7:9: warning: too many arguments for format [-Wformat-extra-args] printf("a=%llu\n",a); ^~~~~~~~~~ test_size_t.c:8:13: warning: unknown conversion type character 'z' in format [-Wformat=] printf("a=%zu\n",a); ^ test_size_t.c:8:9: warning: too many arguments for format [-Wformat-extra-args] printf("a=%zu\n",a); ^~~~~~~~~ test_size_t.c:8:13: warning: unknown conversion type character 'z' in format [-Wformat=] printf("a=%zu\n",a); ^ test_size_t.c:8:9: warning: too many arguments for format [-Wformat-extra-args] printf("a=%zu\n",a); ^~~~~~~~~ test_size_t.c:9:9: warning: ISO C does not support the 'I64' ms_printf length modifier [-Wformat=] printf("a=%I64u\n",a); ^~~~~~~~~~~ test_size_t.c:9:9: warning: ISO C does not support the 'I64' ms_printf length modifier [-Wformat=] 

我想在没有警告的情况下printf一个size_t,但在这种情况下不知道正确的格式说明符。

问题不是编译器而是C库。 MinGW使用Microsoft的“Visual C Runtime”( msvcrt ),它只符合c89 ,不支持z格式说明符。

以下是使用MinGW时可以安全打印size_t方法:

 #include  #include  #ifdef _WIN32 # ifdef _WIN64 # define PRI_SIZET PRIu64 # else # define PRI_SIZET PRIu32 # endif #else # define PRI_SIZET "zu" #endif int main(void) { size_t mySize = 24; printf("%" PRI_SIZET "\n", mySize); } 

在win64上,您将收到此代码的警告,因为PRIu64扩展为msvcrt特定的I64u格式说明符。 但是你可以用GCC标志-Wno-pedantic-ms-format来使这个警告静音。


请注意,你需要一个long long类似的技巧(这里使用32位和64位窗口上的msvcrt )因为msvcrt也不知道ll


编辑 :正如@MM在评论中指出的那样,您可以使用#define __USE_MINGW_ANSI_STDIO 1链接MinGW提供的支持C11的替代stdio函数。 如果我可以绕过msvcrt的特性,我宁愿不链接额外的代码,但这当然是品味的问题。

注释中提到的替代解决方案是__USE_MINGW_ANSI_STDIO编译器开关:

 #define __USE_MINGW_ANSI_STDIO 1 #include  int main(void) { size_t a = 100; printf("a=%lu\n",a); printf("a=%llu\n",a); printf("a=%zu\n",a); printf("a=%I64u\n",a); } 

这使代码按预期编译,gcc现在提供适当的警告:

 warning: format '%lu' expects argument of type 'long unsigned int', but argument 2 has type 'size_t' [-Wformat=] warning: ISO C does not support the 'I' printf flag [-Wformat=] warning: format '%u' expects argument of type 'unsigned int', but argument 2 has type 'size_t' [-Wformat=]