编译器在打印变量地址时发出警告

Compiler gives warning when printing the address of a variable

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

#include<stdio.h>

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

但是,Clang-3.7 编译器发出警告如下:

warning: format specifies type 'unsigned int' but the argument has type 'int *' [-Wformat]`

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

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

我从 gcc.godbolt.org

编译了我的程序

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

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

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

C11, Reference:

p The argument shall be a pointer to void. The value of the pointer is converted to a sequence of printing characters, in an implementation-defined manner.

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

GCC 5.1 确实在我的系统上产生了警告,没有任何额外的 选项。 GCC godbolt produces warnings 具有更严格的编译器选项:-Wall -Wextra。通常,您应该使用最严格的编译器选项进行编译。

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

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

But, when I compiled with GCC-5.x, it gave no warnings

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


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

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

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

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

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

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

希望对您有所帮助。