Разница между указателем на указатель и указателем на массив? - PullRequest
13 голосов
/ 25 июня 2011

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

#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 с), почему я не могу присвоить &a до p1?

Ответы [ 3 ]

16 голосов
/ 25 июня 2011

Строка 11 -

        p1 = &a;

, где p1 имеет тип int **, а a имеет тип int[3], верно?

Хорошо;&a имеет тип int(*)[3], и этот тип не совместим с int**, как сказал вам компилятор

Вы можете попробовать

        p1 = &p0;

И прочитать c-faq , в частности раздел 6.

Вкратце: массивы не являются указателями , а указатели не являются массивами .

6 голосов
/ 25 июня 2011

a не является указателем на int, он распадается на такие в определенных ситуациях.Если бы &a был типа int **, вы не могли бы использовать его для инициализации p2, не так ли?

Вам нужно сделать p1 = &p0; для нужного эффекта.«указатель на указатель» означает «по этому адресу вы найдете указатель».Но если вы посмотрите на адрес &a, вы обнаружите массив (очевидно), поэтому int ** не правильный тип.

0 голосов
/ 25 июня 2011

Для многих операций a подразумевает &a, и оба возвращают одно и то же: адрес первого элемента в массиве.

Вы не можете получить адрес указателя, потому что переменная не хранит указатель. a не является указателем, хотя в некоторых случаях он ведет себя как один.

...