Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is and how to solve the warning: format ‘%p’ expects argument of type ‘void *’, but argument 2 has type ‘int *’ [-Wformat=] when printing it out

I have the following code:

#include<stdio.h>

int main(void){
  int array[5]={10,20,30,40,50};
  int *p;
  p=array;
  printf("%p\n", array);
  printf("%p\n", p);
  printf("%p\n", &array[0]);
  printf("%p\n", &p[0]);
  printf("%p\n", &(*array));

  return 0;
}

Compiling this code with GCC and printing the values of the addresses out with %p gives the following warnings:

01.c: In function ‘main’:
01.c:7:12: warning: format ‘%p’ expects argument of type ‘void *’, but argument 2 has type ‘int *’ [-Wformat=]    printf("%p\n", array);
           ~^     ~~~~~
           %ls
01.c:8:12: warning: format ‘%p’ expects argument of type ‘void *’, but argument 2 has type ‘int *’ [-Wformat=]    printf("%p\n", p);
           ~^     ~
           %ls
01.c:9:12: warning: format ‘%p’ expects argument of type ‘void *’, but argument 2 has type ‘int *’ [-Wformat=]    printf("%p\n", &array[0]);
           ~^     ~~~~~~~~~
           %ls
01.c:10:12: warning: format ‘%p’ expects argument of type ‘void *’, but argument 2 has type ‘int *’ [-Wformat=]    printf("%p\n", &p[0]);
           ~^     ~~~~~
           %ls
01.c:11:12: warning: format ‘%p’ expects argument of type ‘void *’, but argument 2 has type ‘int *’ [-Wformat=]    printf("%p\n",
&(*array));
           ~^     ~~~~~~~~~
           %ls ```

How can I solve them and why are they happening? Also, what is %ls?


1 Answers

An object pointer of any type may be implicitly converted to a void * without a cast, and the reverse is also true.

However, the %p format specifier to printf explicitly expects a void * argument, and because printf is a variadic function that implicit conversion won't happen.

This is one of the rare cases when an explicit cast to void * is required:

printf("%p\n", (void *)array);
printf("%p\n", (void *)p);
printf("%p\n", (void *)&array[0]);
printf("%p\n", (void *)&p[0]);
printf("%p\n", (void *)&(*array));

On most implementations you're likely to come in contact with, objects pointers and void * have the same representation. However that is not necessarily true in general, and failing to cast can cause undefined behavior on systems where this is not true.

In contrast, calling the function foo below does not require a cast:

void foo(void *p)
{
    printf("p=%p\n", p);
}

int main()
{
    int x;
    foo(&x);
}

Because the type of the parameter is known at compile time.

like image 95
dbush Avatar answered Sep 04 '25 23:09

dbush



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!