Подтвердить что ты не робот

Разница между указателем на указатель и указателем на массив?

Учитывая, что имя массива на самом деле является указателем на первый элемент массива, следующий код:

#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?

4b9b3361

Ответ 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 не является указателем, хотя в некоторых случаях он ведет себя как один.