Указатель всего массива

    int main(){
        int a[][3] = {1,2,3,4,5,6};
        int (*ptr)[3]=a;
        printf(" %d",(*ptr)[1]) ;
    }

Я знаю, что переменная ptr является указателем первого массива 1d типа int, другими словами, переменная ptr будет хранить адрес первых трех целых чисел, сначала предположим, что базовый адрес a равен 1000, так что, как я думаю этот 2d массив будет храниться в памяти в таком виде:

elements:                  |    1     |    2     |    3     ||    4     |    5     |    6     |
addressed of each element: |   1000   | 1004     | 1008     ||   1012   | 1016     | 1020     |
                           ---------------------------------||---------------------------------
addressed of each array:                1000                              1012

Таким образом, ptr будет хранить значение 1000, которое является адресом первого массива. А это значит, что *ptr или (*ptr)[0] дадут мне адрес первого элемента, а *ptr+1 или ((*ptr)[1]) дадут мне адрес второго элемента и так далее.

Я так понимаю *ptr[1] даст адрес второго элемента, а не его значение.

Но из вывода кажется, что я ошибаюсь. Поэтому я хочу знать, в чем проблема в моем процессе.

Выход 2

anas 20.02.2023 10:48

Надеюсь, вы видите, что на самом деле вы инициализируете не двумерный массив, а точнее — массив массивов.

Shark 20.02.2023 14:47

Нет, я сделал, потому что даже если я не использовал скобки для массивов внутри исходных скобок, компилятор увидит, что у меня есть несколько массивов внутри скобок, потому что я сказал Подоле, что создам 3 столбца для каждого массива, поэтому компилятор увидит 6 столбцов, что составляет 3 столбца плюс 3 столбца, и он поймет, что у меня есть два массива по три элемента для каждого

anas 20.02.2023 15:59
T - 1Bits: Генерация последовательного массива
T - 1Bits: Генерация последовательного массива
По мере того, как мы пишем все больше кода, мы привыкаем к определенным способам действий. То тут, то там мы находим код, который заставляет нас...
Что такое деструктуризация массива в JavaScript?
Что такое деструктуризация массива в JavaScript?
Деструктуризация позволяет распаковывать значения из массивов и добавлять их в отдельные переменные.
0
3
90
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Рассмотрим выражение, используемое при вызове printf

printf(" %d",(*ptr)[1]) ;

Для начала указатель ptr указывает на первый элемент типа int[3] двумерного массива.

int (*ptr)[3]=a;

Это связано со списком инициализаторов

int a[][3] = {1,2,3,4,5,6};

Двумерный массив имеет два элемента типа int[3].

Таким образом, разыменовав указатель *ptr, вы получите lvalue типа int[3], который представляет собой одномерный массив. Затем к этому массиву применяется индексный оператор ( *ptr )[1], который дает второй элемент одномерного массива.

Таким образом, будет выведено значение 2.

А это значит, что *ptr или (*ptr)[0] даст мне адрес первого элемент

Выражение *ptr и ( *ptr )[0] — это две сущности разных типов. The expression*ptryields lvalue of the typeint[3]` , Use din-выражения в свою очередь могут быть неявно преобразованы в указатель на первый элемент полученного массива.

Выражение ( *ptr )[0] дает первый скалярный элемент полученного массива типа int.

Я так понимаю *ptr[1] выдаст адрес второго элемент, а не его значение.

Выражение ptr[1] дает второй элемент типа int[3] двумерного массива В этом выражении *ptr[1] полученный объект типа int[3] неявно преобразуется в указатель типа int * и разыменование указателя дает первый элемент типа int из второй элемент двумерного массива.

Чтобы было понятнее, рассмотрим, как оценивается оператор нижнего индекса.

Например, выражение ptr[0] эквивалентно *( ptr + 0 ), которое, в свою очередь, эквивалентно *ptr.

Выражение (*ptr)[1] эквивалентно ptr[0][1].

Выражение *ptr[1] эквивалентно *(ptr[1] ), которое, в свою очередь, эквивалентно ptr[1][0].

В общем случае выражение ptr[i][j] можно переписать несколькими способами. Например

( *( ptr + i ) )[j]
*( *( ptr + i ) + j )
*( ptr[i] + j )
Ответ принят как подходящий

Вы правы до этой части:

А это значит, что *ptr или (*ptr)[0] дадут мне адрес первого элемента

*ptr сделает это. (*ptr)[0] разыменует указатель массива, а затем разыменует результирующий массив, дав вам значение первого элемента, 1.

Точно так же (*ptr)[1]) сначала даст вам массив, а затем второй элемент в этом массиве, 2.

Насколько я понимаю, *ptr[1] даст адрес второго элемента, а не его значение.

Нет, поскольку [] имеет более высокий приоритет, чем *, ptr[1] сначала даст вам (адрес) второго массива. Затем вы разыменовываете его и получаете значение первого элемента во втором массиве, 4.

Ключевым моментом здесь является то, что как только вы разыграете указатель на массив, вы получите массив, который будет вести себя так же, как любой массив с точки зрения «распада массива» и т. д.


Лучшие практики:

  • Не отменяйте ссылки на указатели массива с помощью *, если вы можете этого избежать. ptr[0][0] гораздо менее двусмыслен. Этот синтаксис и есть весь смысл использования указателей массива в данном случае.
  • Избегайте небрежных списков инициализаторов, таких как int a[][3] = {1,2,3,4,5,6};. C позволяет это, но это дурной стиль и приглушает некоторые возможности диагностики. Вместо этого это должен был быть int a[][3] = { {1,2,3}, {4,5,6} };, который в качестве бонуса также является читаемым, самодокументируемым кодом.

Хорошо, могу я сказать (*ptr)[0]=*(*ptr+0)?

anas 20.02.2023 11:15

@anas Да, (*ptr)[0] то же самое, что и *((*ptr)+0), то же самое, что и *(*ptr+0), то же самое, что и *(*ptr), то же самое, что и **ptr. И это тоже самое, что и ptr[0][0].

Ian Abbott 20.02.2023 11:19

@anas something[n] по определению на 100% эквивалентен *( (something) + (n) ) и не имеет ничего общего с указателями на массивы как таковые.

Lundin 20.02.2023 11:21

Во-первых, рекомендуется включить предупреждения компилятора. Затем вы будете проинформированы об отсутствующих фигурных скобках в инициализаторе. Вот слегка подчищенная версия вашей программы:

#include <stdio.h>

int main(void)
{
    int a[][3] = {{1, 2, 3}, {4, 5, 6}};
    int (*ptr)[3] = a;
    printf("%d\n", (*ptr)[1]);
    return 0;
}

Если вы запустите его, вы получите вывод «2». Это связано с тем, что *ptr является первым элементом массива a, который сам является массивом, и поэтому (*ptr)[1] является вторым элементом в этом содержащемся массиве, который равен 2.

Другие вопросы по теме