How to printf a size_t without warning in mingw-w64 gcc 7.1?

前端 未结 3 1036
忘了有多久
忘了有多久 2020-11-27 07:57

I am using the mingw-w64 (x64) fork of minGW as prepared on nuwen.net. This is from the 7.1 version of gcc :

gcc --version
gcc (GCC) 7.1.0

相关标签:
3条回答
  • 2020-11-27 08:40

    The alternative solution as mentioned in comments is to toss in the __USE_MINGW_ANSI_STDIO compiler switch:

    #define __USE_MINGW_ANSI_STDIO 1
    
    #include <stdio.h>
    
    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);
    }
    

    This makes the code compile as expected and gcc now gives the appropriate warnings:

    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=]  
    

    Alternatively you can define the macro on command line with -D__USE_MINGW_ANSI_STDIO=1

    0 讨论(0)
  • 2020-11-27 08:42

    The problem is not the compiler but the C library. MinGW uses Microsoft's "Visual C Runtime" (msvcrt) which only conforms to c89 and it doesn't support the z format specifier.

    Here's what you can do to safely print a size_t when using MinGW:

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

    On win64, you would get a warning with this code, because PRIu64 expands to the msvcrt-specific I64u format specifier. But you can silence this warning with the GCC flag -Wno-pedantic-ms-format.


    Note that you need a similar trick for long long (here using PRIu64 on both 32bit and 64bit windows) because msvcrt doesn't know ll either.


    edit: as pointed out by @M.M in a comment, you can instead link MinGW-provided alternative stdio functions that support C11 with #define __USE_MINGW_ANSI_STDIO 1. I prefer not to link extra code if I can get around the peculiarities of msvcrt, but that's of course a matter of taste.

    0 讨论(0)
  • 2020-11-27 08:45

    PRIuPTR trick works (Cross platform format string for variables of type size_t?):

    #include <stdio.h>
    #include <inttypes.h>
    int main()
    {
        size_t a = (size_t)(1024ULL * 1024 * 1024 * 1024 + 13);
        printf("a                 = %" PRIuPTR "\n", a);
        printf("sizeof(size_t)    = %" PRIuPTR "\n", sizeof(size_t));
        printf("sizeof(uintptr_t) = %" PRIuPTR "\n", sizeof(uintptr_t));
        return 0;
    }
    

    Output x86:

    a                 = 13
    sizeof(size_t)    = 4
    sizeof(uintptr_t) = 4
    

    Output x64:

    a                 = 1099511627789
    sizeof(size_t)    = 8
    sizeof(uintptr_t) = 8
    
    0 讨论(0)
提交回复
热议问题