【问题标题】:Compiler gives warning when printing the address of a variable编译器在打印变量地址时发出警告
【发布时间】:2016-04-15 20:27:04
【问题描述】:

我做了一个非常简单的程序来打印两个变量的地址。

#include<stdio.h>

int main()
{
    int a,b;
    printf("%u\n%u",&a,&b);
    return 0;
}

但是,Clang-3.7 编译器给出警告为:

警告:格式指定类型'unsigned int',但参数的类型为'int *' [-Wformat]`

但是,当我使用 GCC-5.x 编译时,它没有给出任何警告。其中哪一个是正确的?

我知道的一件事是unsigned int num=&amp;a; 是错误的,因为地址只能存储在指针中。但是,编译器在打印地址时发出警告是否正确?

我从gcc.godbolt.org编译我的程序

【问题讨论】:

  • GCC,如果配置正确 (-Wall) 给出:warning: format '%u' expects argument of type 'unsigned int', but argument 2 has type 'int *' [-Wformat=]
  • 我认为这个问题(以及发布的答案)是一个很好的规范副本的候选者:) 将它添加到收藏夹。

标签: c gcc printf clang format-specifiers


【解决方案1】:

%p 是打印地址的正确格式说明符:

printf("%p\n%p",(void*)&a, (void*)&b);

C 标准要求对应于%p 的参数应该是void* 类型。所以演员表就在那里。

C11,Reference

p 参数应该是一个指向 void 的指针。指针的值 转换为打印字符序列,在 实现定义的方式。

使用不正确的格式说明符是undefined behavior。编译器不需要为未定义的行为生成任何诊断。所以 gcc 和 clang 都是正确的。

GCC 5.1 确实会在我的系统上产生警告,而无需任何额外的 选项。 GCC godbolt produces warnings 具有更严格的编译器选项:-Wall -Wextra。一般来说,您应该使用最严格的编译器选项进行编译。

【讨论】:

  • 恕我直言,-Wextra 不是 this 案例所必需的。 -Wall 应该足够了。只是说:)
  • @SouravGhosh 只需-Wformat 就足以找到这个特殊 问题。但总的来说,两者都编译是个好主意。
  • 完全同意。只是想指出 exact 选项,仅此而已。干杯。
【解决方案2】:

打印地址(指针)的正确格式说明符是%p,您需要将参数转换为void *

因此,警告是有效的并且应该存在。

但是,当我使用 GCC-5.x 编译时,它没有给出警告

如果是gcc,请包含-Wall注意编译器选项并尝试编译。我相信它会抛出我们期望的(相同的)警告。


注意:实际上,-Wformat 会检查提供给 printf()scanf() 家庭调用的参数的类型。 -Wall 启用 -Wformat

【讨论】:

  • 感谢您的帮助 :-)
【解决方案3】:

您收到此错误是因为格式说明符 %u 接受 unsigned-integer,而您在代码中提供的是指向内存位置的指针。

您可以通过将参数类型指定为(void*)来打印指针所持有的内存位置的地址,这将不会产生错误并以十进制格式打印内存位置的地址。

printf("%u\n%u",(void*)&a,(void*)&b);

另外,这不是打印指针的正确方法,正确的方法是使用说明符%p,它将以十六进制格式打印内存位置的地址。

printf("%p\n%p",(void*)&a,(void*)&b); 

希望对您有所帮助。

【讨论】:

    猜你喜欢
    • 2019-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-13
    • 1970-01-01
    • 2016-07-06
    • 1970-01-01
    相关资源
    最近更新 更多