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

时间:2016-01-11 13:44:53

标签: c gcc printf clang format-specifiers

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

#include<stdio.h>

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

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

  

警告:格式指定类型&#39; unsigned int&#39;但是参数的类型为&#39; int *&#39; [-Wformat]`

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

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

我从gcc.godbolt.org

编译了我的程序

3 个答案:

答案 0 :(得分:9)

DROP TABLE IF EXISTS my_table; CREATE TABLE my_table (id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,string VARCHAR(12) NOT NULL); INSERT INTO my_table (string) VALUES ('2b'),('1'),('2a'),('1b'),('1a'),('11'); SELECT * FROM my_table; +----+--------+ | id | string | +----+--------+ | 1 | 2b | | 2 | 1 | | 3 | 2a | | 4 | 1b | | 5 | 1a | | 6 | 11 | +----+--------+ SELECT * FROM my_table ORDER BY string + 0,string; +----+--------+ | id | string | +----+--------+ | 2 | 1 | | 5 | 1a | | 4 | 1b | | 3 | 2a | | 1 | 2b | | 6 | 11 | +----+--------+ 是打印地址的正确格式说明符:

%p

C标准要求与printf("%p\n%p",(void*)&a, (void*)&b); 对应的参数应为%p类型。所以演员都在那里。

C11,Reference

  

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

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

GCC 5.1确实在我的系统上发出警告而没有任何额外的警告 选项。和GCC godbolt produces warnings有更严格的编译器选项:void*。通常,您应该使用最严格的编译器选项进行编译。

答案 1 :(得分:4)

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

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

  

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

如果是void *,请添加gcc 注意编译器选项并尝试编译。我相信它会抛出我们期待的(相同)警告。

注意:实际上是-Wall,它会检查-Wformatprintf()家庭电话的提供参数的类型。 scanf()启用-Wall

答案 2 :(得分:0)

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

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

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

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

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

希望有所帮助。