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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在mingw-w64 gcc 7.1中无需警告地打印size_t?相关的知识,希望对你有一定的参考价值。

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

gcc --version
gcc (GCC) 7.1.0

我正在编译这个程序:

#include <stdio.h>

int main(void)
{
    size_t a = 100;
    printf("a=%lu
",a);
    printf("a=%llu
",a);
    printf("a=%zu
",a);
    printf("a=%I64u
",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
",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
",a);
                ~~^
                %I64u
    test_size_t.c:7:14: warning: unknown conversion type character 'l' in format [-Wformat=]
      printf("a=%llu
",a);
                  ^
    test_size_t.c:7:9: warning: too many arguments for format [-Wformat-extra-args]
      printf("a=%llu
",a);
             ^~~~~~~~~~
    test_size_t.c:7:14: warning: unknown conversion type character 'l' in format [-Wformat=]
      printf("a=%llu
",a);
                  ^
    test_size_t.c:7:9: warning: too many arguments for format [-Wformat-extra-args]
      printf("a=%llu
",a);
             ^~~~~~~~~~
    test_size_t.c:8:13: warning: unknown conversion type character 'z' in format [-Wformat=]
      printf("a=%zu
",a);
                 ^
    test_size_t.c:8:9: warning: too many arguments for format [-Wformat-extra-args]
      printf("a=%zu
",a);
             ^~~~~~~~~
    test_size_t.c:8:13: warning: unknown conversion type character 'z' in format [-Wformat=]
      printf("a=%zu
",a);
                 ^
    test_size_t.c:8:9: warning: too many arguments for format [-Wformat-extra-args]
      printf("a=%zu
",a);
             ^~~~~~~~~
    test_size_t.c:9:9: warning: ISO C does not support the 'I64' ms_printf length modifier [-Wformat=]
      printf("a=%I64u
",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使用微软的“Visual C Runtime”(msvcrt),它只符合,并且不支持z格式说明符。

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

#include <inttypes.h>
#include <stdio.h>

#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 "
", mySize);
}

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


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


编辑:正如@ M.M在评论中所指出的,您可以将MinGW提供的替代stdio函数与#define __USE_MINGW_ANSI_STDIO 1相关联。如果我可以解决msvcrt的特点,我宁愿不链接额外的代码,但这当然是品味的问题。

另一答案

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

#define __USE_MINGW_ANSI_STDIO 1

#include <stdio.h>

int main(void)
{
    size_t a = 100;
    printf("a=%lu
",a);
    printf("a=%llu
",a);
    printf("a=%zu
",a);
    printf("a=%I64u
",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=]  

以上是关于如何在mingw-w64 gcc 7.1中无需警告地打印size_t?的主要内容,如果未能解决你的问题,请参考以下文章

Windows 64x下的GCC中的printf和%llx

为啥 GCC 开始警告获取 void 表达式的地址?

如何在 uint64_t 中移动 >= 32 位?

Fedora dnf gcc 时候警告/etc/pki/rpm-gpg/RPM-GPG-KEY-fedora-x86_64问题

如何消除 GCC 中的外部库/第三方警告 [重复]

在 GCC 中使用不同枚举类型分配或执行算术时如何发出警告?