Compiler gives warning when printing the address o

2019-03-05 07:02发布

问题:

I made a very simple program to print the address of two variables.

#include<stdio.h>

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

But, the Clang-3.7 compiler gives warning as:

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

But, when I compiled with GCC-5.x, it gave no warnings. Which of them is correct?

One thing I know is that doing unsigned int num=&a; would be wrong as address can only be stored in a pointer. But, is it correct for the compiler to give warning when printing the address?

I compiled my program from gcc.godbolt.org

回答1:

%p is the correct format specifier to print addresses:

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

The C standard requires that the argument corresponding to %p should be of type void*. So the casts are there.

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.

Using incorrect format specifier is undefined behavior. A compiler is not required to produce any diagnostics for undefined behaviors. So both are gcc and clang are correct.

GCC 5.1 does produce warnings on my system without any additional options. And GCC godbolt produces warnings with stricter compiler options: -Wall -Wextra. In general, you should compile with strictest compiler options.



回答2:

The correct format specifier for printing an address (pointer) is %p and you need to cast the argument to void *.

Hence, the warning is valid and should be there.

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

In case of gcc, please include -WallNote compiler option and try to compile. I believe it will throw the (same) warning we're expecting.


Note: Actually, -Wformat, which checks for the type of supplied argument to printf() and scanf() family calls. -Wall enables -Wformat.



回答3:

You got this error because format-specifier %u accepts unsigned-integer, whereas what you are supplying in your code is a pointer to a memory location.

You can print address of memory location held by pointer by specifying type of the argument as (void*), this will generate no errors and print the address of memory location in decimal format.

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

Also, this is not the correct way to print a pointer, the correct way is to use specifier %p, which will print the address of the memory location in hexadecimal format.

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

Hope that helps.