【问题标题】:I have having following warning in gcc compilation in 32 bit architecture but not having any such warning in 64 bit architecture我在 32 位架构中的 gcc 编译中有以下警告,但在 64 位架构中没有任何此类警告
【发布时间】:2010-03-11 15:18:09
【问题描述】:

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' 

在符号.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

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

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 位架构中编译而不会发出警告?

它的解决方案是什么?

【问题讨论】:

    标签: 32bit-64bit gcc-warning


    【解决方案1】:

    使用%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
    

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

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

    【讨论】:

    • 确实对两者都有效,我在同一行又收到了一个新警告,即 ISO C90 不支持 'z' gnu_printf 长度修饰符。在这种情况下有什么替代方案?
    • 编译时使用 -std=c99,或者 #define 格式说明符,例如FMT_SIZE_T 在 64 位版本上被定义为 %llu,在 32 位版本上被定义为 %lu
    • 是否可以在不依赖 C99 标准的情况下删除此类警告?
    • @thetna:是的,正如我所说,你可以有条件地#define你自己的FMT_SIZE_T,例如%lu 用于 32 位版本,%llu 用于 64 位版本
    • @pual 感谢您的回复。这可能又是一个愚蠢的问题,但我是 C 的新手。这些更改是否使单个包与架构环境兼容,还是需要为 32 位和 64 位架构单独定义 %lu?
    【解决方案2】:

    我发现%lu 是 linux 上size_t 的唯一符合 C89(或符合 gcc-c89-warnings)的格式。在 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 中,all printf 格式指的是特定的原始类型(longint 等),但在 all C 方言中,size_t 是平台-依赖(可能是longint 或其他)。

    像往常一样,微软会为您提供自己的特殊活动扳手。 Windows 编译环境是一个严重修改的 C89:它有 long long,但没有 ll printf 修饰符。在 windows-land 中,%llu 变为 %I64u%zu 变为 %Iu

    我最终在我实验室的代码库中使用了以下代码:

    #ifdef _WIN32 #define PRIuZ "Iu" #别的 #define PRIuZ "lu" #万一

    使用:

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

    我根据 C99 的 inttypes.h 中的定义对名称进行建模。

    除此之外:我的 win64 mingw-gcc 版本(4.4.5 20100527 (prerelease) [svn/rev.159909 - mingw-w64/oz]),加上-Wall-pedantic总是 strong> 在打印 size_t 时发出警告。它抱怨%I64u%Iu 是非标准的,而%lu 是不正确的。似乎编译器正确地被微软的疯狂所绊倒。我不得不使用-pedantic -Wformat=0 让它不抱怨%Iu

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-05-11
      • 1970-01-01
      • 2020-03-19
      • 2011-02-03
      • 1970-01-01
      • 1970-01-01
      • 2011-01-22
      • 1970-01-01
      相关资源
      最近更新 更多