J'utilise la fourche mingw-w64 (x64) de minGW telle que préparée sur nuwen.net. Cela provient de la version 7.1 de gcc:
gcc --version
gcc (GCC) 7.1.0
Je compile ce programme:
#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);
}
avec avertissements et norme c11:
gcc -Wall -Wextra -Wpedantic -std=c11 test_size_t.c
et je reçois ces avertissements:
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=]
Je voudrais imprimer un size_t sans avertissement, mais je ne connais pas le spécificateur de format correct dans cette situation.
Le problème n'est pas le compilateur mais la bibliothèque C. MinGW utilise le "Visual C Runtime" de Microsoft (msvcrt
) qui est uniquement conforme à c89 et ne prend pas en charge le spécificateur de format z
.
Voici ce que vous pouvez faire pour imprimer un size_t
en toute sécurité avec 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);
}
Sur win64, vous recevez un avertissement avec ce code, car PRIu64
se développe en spécificateur de format msvcrt
-spécifique I64u
. Mais vous pouvez désactiver cet avertissement avec l'indicateur GCC -Wno-pedantic-ms-format
.
Notez que vous avez besoin d'une astuce similaire pour long long
(ici, en utilisant PRIu64
sur les fenêtres 32 bits et 64 bits), car msvcrt
ne sait pas ll
non plus.
edit : comme l'a souligné @ M.M dans un commentaire, vous pouvez lier à la place des fonctions alternatives stdio
fournies par MinGW qui prennent en charge C11 avec #define __USE_MINGW_ANSI_STDIO 1
. Je préfère ne pas lier de code supplémentaire si je peux contourner les particularités de msvcrt
, mais c'est bien sûr une question de goût.
La solution alternative mentionnée dans les commentaires consiste à lancer dans le commutateur de compilation __USE_MINGW_ANSI_STDIO
:
#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);
}
Cela rend le code compilé comme prévu et gcc donne maintenant les avertissements appropriés:
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=]