Отношение между указателями и массивами в C - PullRequest
0 голосов
/ 30 апреля 2020

У меня есть 3 случая из сертификации CLA (C Сертификация сертифицированного специалиста по языку программирования; CPP Институт), которые я хотел бы понять лучше:

  1. int *array[10]
  2. int (*array)[10]
  3. int *(*array)[10]

В чем различия между этими 3 случаями?

Ответы [ 2 ]

2 голосов
/ 30 апреля 2020

Вот что у вас есть:

  1. Массив из 10 указателей на int.
  2. Указатель на массив из 10 int.
  3. Указатель на массив из 10 указателей на int.
0 голосов
/ 30 апреля 2020

Это

int *array[10]

является объявлением массива с 10 элементами типа int *.

Вот демонстрационная программа.

#include <stdio.h>

int main(void) 
{
    enum { N = 10 };
    int a[N] = 
    { 
        0, 1, 2, 3, 4, 5, 6, 7, 8, 9 
    };

    int * array[N] = 
    { 
        &a[0], &a[1], &a[2], &a[3], &a[4], &a[5], &a[6], &a[7], &a[8], &a[9] 
    };

    for ( size_t i = 0; i < N; i++ )
    {
        printf( "%d ", a[i] );
    }
    putchar( '\n' );

    for ( size_t i = 0; i < N; i++ )
    {
        printf( "%d ", *array[i] );
    }
    putchar( '\n' );

    return 0;
}

Его вывод

0 1 2 3 4 5 6 7 8 9 
0 1 2 3 4 5 6 7 8 9 

Этот

int (*array)[10]

является объявлением указателя на объект, имеющий тип массива int[10].

Вот еще одна демонстрационная программа .

#include <stdio.h>

int main(void) 
{
    enum { N = 10 };
    int a[N] = 
    { 
        0, 1, 2, 3, 4, 5, 6, 7, 8, 9 
    };

    int (*array)[N] = &a;

    for ( size_t i = 0; i < N; i++ )
    {
        printf( "%d ", a[i] );
    }
    putchar( '\n' );

    for ( size_t i = 0; i < N; i++ )
    {
        printf( "%d ", ( *array )[i] );
    }
    putchar( '\n' );

    return 0;
}

Его вывод такой же, как и выше.

0 1 2 3 4 5 6 7 8 9 
0 1 2 3 4 5 6 7 8 9 

Этот

int *(*array)[10]

является объявлением указателя на объект типа массива int *[10].

Вот еще одна демонстрационная программа.

#include <stdio.h>

int main(void) 
{
    enum { N = 10 };
    int a[N] = 
    { 
        0, 1, 2, 3, 4, 5, 6, 7, 8, 9 
    };

    int * b[N] = 
    { 
        &a[0], &a[1], &a[2], &a[3], &a[4], &a[5], &a[6], &a[7], &a[8], &a[9] 
    };

    int *(*array)[N] = &b;

    for ( size_t i = 0; i < N; i++ )
    {
        printf( "%d ", a[i] );
    }
    putchar( '\n' );

    for ( size_t i = 0; i < N; i++ )
    {
        printf( "%d ", *( *array )[i] );
    }
    putchar( '\n' );

    return 0;
}

Снова ее вывод такой же, как показано выше.

0 1 2 3 4 5 6 7 8 9 
0 1 2 3 4 5 6 7 8 9 

В общем, если у вас есть например, массив

T a[N1][N2][N3];

, где T - некоторый спецификатор типа, а N1, N2, N3 - его размеры, тогда указатель на такой массив будет выглядеть как

T ( *p )[N1][N2][N3] = &a;

Разыменовав указатель, вы получите lavlue самого массива.

Например,

sizeof( *p ) равно sizeof( a[N1][N2][N3] ).

B Ниже приведен пример более сложного объявления

int * ( * array[10] )[10];

Это объявление массива из 10 элементов указателей на массивы из 10 элементов указателя типа int.

Здесь демонстрационная программа, которая показывает, как обрабатывать такой массив Расследуйте его .:)

#include <stdio.h>

int main(void) 
{
    enum { N = 10 };
    int a[N] = 
    { 
        0, 1, 2, 3, 4, 5, 6, 7, 8, 9 
    };

    int * b[N] = 
    { 
        &a[0], &a[1], &a[2], &a[3], &a[4], &a[5], &a[6], &a[7], &a[8], &a[9] 
    };

    int * ( * array[N] )[N] = 
    { 
        &b, &b, &b, &b, &b, &b, &b, &b, &b, &b
    };

    for ( size_t i = 0; i < N; i++ )
    {
        for ( size_t j = 0; j < N; j++ )
        {
            printf( "%d ",  ( **array[i] )[j] );
        }           
        putchar( '\n' );
    }
    putchar( '\n' );

    return 0;
}

Вывод программы:

0 1 2 3 4 5 6 7 8 9 
0 1 2 3 4 5 6 7 8 9 
0 1 2 3 4 5 6 7 8 9 
0 1 2 3 4 5 6 7 8 9 
0 1 2 3 4 5 6 7 8 9 
0 1 2 3 4 5 6 7 8 9 
0 1 2 3 4 5 6 7 8 9 
0 1 2 3 4 5 6 7 8 9 
0 1 2 3 4 5 6 7 8 9 
0 1 2 3 4 5 6 7 8 9 
...