我在32位架构的gcc编译中有以下警告,但在64位架构中没有任何此类警告

时间:2010-03-11 15:18:09

标签: 32bit-64bit gcc-warning

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' 

在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 }

SYMBOL定义为:

typedef size_t SYMBOL

当我用'%zu'替换'%ld'时,我收到以下警告:

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

注意:从2010年3月26日开始编辑,由于与上述问题的相似性,因此添加了以下问题。

我有以下声明:

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 个答案:

答案 0 :(得分:4)

使用%zu而不是%ld作为size_t的格式,然后您将在32位和64位版本中获得正确的行为(并且没有警告)。< / p>

如果由于某种原因你无法使用%zu(例如旧的或非标准的编译器),那么你可以这样做:

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

然后,当你需要使用类型为size_t的printf时,你可以这样做:

printf("(sizeof(void *) = %"FMT_SIZE_T" bytes \n", sizeof(void *));

答案 1 :(得分:2)

我认为%lu是Linux上size_t唯一符合C89标准(或符合gcc-c89警告标准)的格式。在glibc下,size_t似乎始终为long unsigned int,因此%lu适用于此。

特别是我发现带有-std=c89 -pedantic-std=c89 -Wall的gcc-4.4.3会警告%llu%lld。有道理,因为他们期望long long,C99类型。

悲剧性的是,无法以独立于平台的C89方式打印size_t。在C89中,所有 printf格式引用特定的原始类型(longint等),但在所有 C方言中,size_t与平台有关(可能是longint或其他内容。

像往常一样,微软会抛出你自己特殊的猴子扳手。 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不正确。似乎编译器正在被微软的疯狂绊倒。我不得不使用-pedantic -Wformat=0让它不要抱怨%Iu