4

I was experimenting with the following C code:

#include <stdio.h>
#include <stdlib.h>

int main(void) {
    int a = 5;
    int *ptr = &a;
    printf("Data stored: %d\n", *ptr); // Simply prints 5.
    printf("Address of variable a: %p\n", (void*) &a);
    printf("Address stored in ptr: %p\n", (void*) ptr);
    return EXIT_SUCCESS;
}

I compiled the program with:

gcc -Wall -Wextra -Wconversion -pedantic -std=c11 -fsanitize=address -fsanitize=undefined example-1.c -o example-1 

I understand that the %p format specifier expects an object address (using & or a valid pointer) but when I compile the code without typecasting to void* it generates a warning:

example-1.c: In function ‘main’:
example-1.c:8:37: warning: format ‘%p’ expects argument of type ‘void *’, but argument 2 has type ‘int *’ [-Wformat=]
     printf("Address of variable a: %p\n", &a);
                                    ~^     ~~
                                    %ls
example-1.c:9:34: warning: format ‘%p’ expects argument of type ‘void *’, but argument 2 has type ‘int *’ [-Wformat=]
     printf("Data stored in ptr: %p\n", ptr);
                                 ~^
                                 %ls

So, I naturally typecast the arguments to void* and then the program works fine, but I cannot make any logical inference about what is actually happening.

strikersps
  • 338
  • 3
  • 16
  • @cmaster-reinstatemonica Ya so that I am able to find out where loss of data can happen due to implicit conversion, if I didn't do that in this case & without typecasting if I ran the program it will run smootly but it will have a undefined behaviour as explained here https://stackoverflow.com/questions/24867814/printfp-and-casting-to-void?noredirect=1&lq=1. My question was why we are typecasting it to `void*` when passing arguments into `printf()` when using `%p` format specifier? – strikersps Oct 08 '20 at 15:45
  • 2
    @Gerhardh Ah, yes. Pointers are not promoted like integers and floats are... Thank you, I learned something today :-) – cmaster - reinstate monica Oct 08 '20 at 16:03
  • 1
    Well i think the quick and dirty answer would just be the cliche " *because the standard mandates that `printf()` when used with the `%p` format specifier must only take `void *` arguments* " and probably for good reason too, given that a `void *` is basically shorthand for *any generic pointer* :) As for why the pointer is not *implicitly* cast to a `void *` , I reckon it is because you are using a compiler that actually primarily compiles C++. In C, conversions to and from `void *` are implicit as the standard. Maybe force the compiler to strictly adhere to the standard and see. – A P Jo Oct 08 '20 at 16:07
  • 1
    @APJo Nah, the missing implicit promotion to `void*` looks like a simple hole in the standard: Any non-function pointer can be implicitly converted to `void*` and back, and must still compare equal to the original. Also, pointers are implicitly converted to/from `void*` when the function prototype is known. Numeric types are canonicalized when passing them to a variadic function. Only pointers are not canonicalized even though they a) can be implicitly converted, b) do not loose information on conversion, c) should be expected to be implicitly converted by all measures of similarity. – cmaster - reinstate monica Oct 08 '20 at 16:18

0 Answers0