У меня было следующее предупреждение при компиляции gcc в 32-битной архитектуре, но не было такого предупреждения в 64-битной архитектуре - PullRequest
2 голосов
/ 11 марта 2010

symbol.c: в функции 'symbol_FPrint':

symbol.c:1209: warning: format '%ld' expects type 'long int', but argument 3 has type 'SYMBOL'
symbol.c: In function 'symbol_FPrintOtter':
symbol.c:1236: warning: format '%ld' expects type 'long int', but argument 3 has type 'SYMBOL'
symbol.c:1239: warning: format '%ld' expects type 'long int', but argument 3 has type 'SYMBOL'
symbol.c:1243: warning: format '%ld' expects type 'long int', but argument 3 has type 'SYMBOL'
symbol.c:1266: warning: format '%ld' expects type 'long int', but argument 3 has type 'SYMBOL' 

In symbol.c

1198 #ifdef CHECK
1199     else {
1200       misc_StartErrorReport();
1201       misc_ErrorReport("\n In symbol_FPrint: Cannot print symbol.\n");
1202       misc_FinishErrorReport();
1203     }
1204 #endif
1205   }
1206   else if (symbol_SignatureExists())
1207     fputs(symbol_Name(Symbol), File);
1208   else
1209     fprintf(File, "%ld", Symbol);
1210 }

И СИМВОЛ определяется как:

typedef size_t SYMBOL

Когда я заменил «% ld» на «% zu», я получил следующее предупреждение:

symbol.c: In function 'symbol_FPrint':
symbol.c:1209: warning: ISO C90 does not support the 'z' printf length modifier

Примечание: здесь оно было отредактировано 26 марта 2010 года, и была добавлена ​​следующая проблема из-за сходства с вышеупомянутой проблемой.

У меня есть следующее утверждение:

printf("\n\t %4d:%4d:%4d:%4d:%4d:%s:%d", Index, S->info, S->weight,
       Precedence[Index],S->props,S->name, S->length);

Предупреждение, которое я получаю при компиляции в 64-битной архитектуре:

format ‘%4d’ expects type ‘int’, but argument 5 has type ‘size_t’

Вот определения параметра:

  NAT    props;
  typedef  unsigned int     NAT;

Как мне избавиться от этого, чтобы можно было без предупреждения компилировать в 32- и 64-битной архитектуре?

Каким может быть ее решение?

Ответы [ 2 ]

4 голосов
/ 11 марта 2010

Используйте %zu вместо %ld в качестве формата для size_t, и тогда вы получите правильное поведение (и без предупреждений) как в 32-битных, так и в 64-битных сборках.

Если по какой-то причине вы не можете использовать %zu (например, старый или нестандартный компилятор), то вы можете сделать что-то вроде этого:

#ifdef __LP64__ // if 64 bit environment
#define FMT_SIZE_T "llu"
#else
#define FMT_SIZE_T "lu"
#endif

Тогда, когда вам нужно использовать printf с чем-то вроде size_t, вы можете сделать это:

printf("(sizeof(void *) = %"FMT_SIZE_T" bytes \n", sizeof(void *));
2 голосов
/ 31 марта 2011

я считаю %lu единственным форматом, совместимым с C89 (или gcc-c89-warnings) для size_t в linux. в glibc size_t кажется всегда long unsigned int, поэтому здесь уместно %lu.

в частности я обнаружил, что gcc-4.4.3 с -std=c89 -pedantic или -std=c89 -Wall будет предупреждать о %llu и %lld. имеет смысл, так как они ожидают long long, типа C99.

К сожалению, нет способа напечатать size_t независимым от платформы способом, совместимым с C89. в C89 все форматы printf относятся к конкретным типам примитивов (long, int и т. д.), но в все диалекты C, size_t зависит от платформы (может быть long или int или что-то еще).

как обычно, майкрософт выдает вам свой специальный обезьяний гаечный ключ. Среда компиляции Windows - плохо модифицированный C89: в ней есть long long, но нет ll модификатора printf. в windows-land %llu становится %I64u, а %zu становится %Iu.

я использовал следующее в кодовой базе моей лаборатории:

#ifdef _WIN32
#define PRIuZ "Iu"
#else
#define PRIuZ "lu"
#endif

использование:

printf("%"PRIuZ"\n", sizeof(struct foo));

Я смоделировал имя из определений в C99 inttypes.h.

в сторону: моя версия win64 mingw-gcc (4.4.5 20100527 (предварительный выпуск) [svn / rev.159909 - mingw-w64 / oz]), плюс -Wall или -pedantic, всегда предупреждает при печати size_t. он жалуется, что %I64u и %Iu нестандартны, а %lu неверен. похоже, что компилятор правильно запутался из-за безумия Microsoft. я должен был использовать -pedantic -Wformat=0, чтобы заставить его не скулить о %Iu.

...