Разница между указателем на указатель и указателем на массив?
Учитывая, что имя массива на самом деле является указателем на первый элемент массива, следующий код:
#include <stdio.h>
int main(void)
{
int a[3] = {0, 1, 2};
int *p;
p = a;
printf("%d\n", p[1]);
return 0;
}
выводит 1
, как ожидалось.
Теперь, учитывая, что я могу создать указатель, указывающий на указатель, я написал следующее:
#include <stdio.h>
int main(void)
{
int *p0;
int **p1;
int (*p2)[3];
int a[3] = {0, 1, 2};
p0 = a;
p1 = &a;
p2 = &a;
printf("p0[1] = %d\n(*p1)[1] = %d\n(*p2)[1] = %d\n",
p0[1], (*p1)[1], (*p2)[1]);
return 0;
}
Я ожидал, что он скомпилирует и напечатает
p0[1] = 1
(*p1)[1] = 1
(*p2)[1] = 1
Но вместо этого во время компиляции это происходит неправильно, говоря:
test.c: In function ‘main’:
test.c:11:5: warning: assignment from incompatible pointer type [enabled by default]
Почему это присвоение неверно? Если p1
является указателем на указатель на int
, а a
является указателем на int
(потому что это имя массива int
s), почему я не могу назначить &a
до p1
?
Ответы
Ответ 1
Строка 11
p1 = &a;
где p1
имеет тип int **
и a
имеет тип int[3]
, right?
Ну; &a
имеет тип int(*)[3]
, и этот тип не совместим с int**
, поскольку компилятор сказал вам
Возможно, вы захотите попробовать
p1 = &p0;
И прочитайте c-faq, в частности раздел 6.
Короче: массивы не указатели, а указатели не являются массивами.
Ответ 2
a
не является указателем на int
, он распадается на такие в определенных ситуациях. Если &a
имел тип int **
, вы не могли бы использовать его для инициализации p2
, не могли бы вы?
Вам нужно сделать p1 = &p0;
для желаемого эффекта. "указатель на указатель" означает "по этому адресу вы найдете указатель". Но если вы посмотрите на адрес &a
, вы найдете массив (очевидно), поэтому int **
не правильный тип.
Ответ 3
Для многих операций a
подразумевает &a
, и оба возвращают одно и то же: адрес первого элемента в массиве.
Вы не можете получить адрес указателя, потому что переменная не хранит указатель. a
не является указателем, хотя в некоторых случаях он ведет себя как один.