Что такое и как решить предупреждение: формат "% p" ожидает аргумент типа "void *", но аргумент 2 имеет тип "int *" [-Wformat =] при его выводе - PullRequest
3 голосов
/ 02 марта 2020

У меня есть следующий код:

#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;
}

Компиляция этого кода с помощью G CC и печать значений адресов с помощью %p дает следующие предупреждения:

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 ```

Как я могу их решить и почему они происходят? Кроме того, что такое %ls?

Ответы [ 2 ]

5 голосов
/ 02 марта 2020

Указатель объекта любого типа может быть неявно преобразован в void * без приведения, и обратное также верно.

Однако спецификатор формата %p для printf явно ожидает void * аргумент, и потому что printf является функцией c от variadi, неявное преобразование не произойдет.

Это один из редких случаев, когда требуется явное приведение к void *:

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));

В большинстве реализаций, с которыми вы можете соприкасаться, указатели объектов и void * имеют такое же представление. Однако в общем случае это не обязательно так, и неудачное приведение может вызвать неопределенное поведение в системах, где это не так.

Напротив, для вызова функции foo ниже не требуется приведение:

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

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

Поскольку тип параметра известен во время компиляции.

1 голос
/ 02 марта 2020

нужен другой тип указателя. Вам нужно привести его к void *

printf("%p\n", array); => printf("%p\n", (void *)array);

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...