2D указатель массива C ++ - PullRequest
       29

2D указатель массива C ++

0 голосов
/ 27 августа 2018
#include <stdio.h>
int main()

    { int arr2D[3][3]; 
    printf("%d\n",((arr2D==*arr2D) && (*arr2D==arr2D[0]))); 
    return o;
    }

То, как значения хранятся в * arr2D и arr2d , одинаково, тогда как arr2D - это указатель константы, который будет хранить адрес первого элемента и arr2D означает значение, присутствующее по адресу, на который указывает arr2D?

Ответы [ 2 ]

0 голосов
/ 27 августа 2018

Это недопустимый код C.

arr2D при использовании в выражении затухает до указателя на первый элемент, int (*)[3].Принимая во внимание, что *arr2D дает первый элемент двумерного массива, int[3], который также затухает при использовании в выражении, в int*.

, поэтому код сравнивает int (*)[3] с int*.Они не являются совместимыми типами указателей и их нельзя сравнивать - это нарушение ограничения стандарта (C17 6.5.9 / 2), и компилятор должен выдать диагностическое сообщение.Это означает, что это серьезная ошибка, и любой, кто попытается попробовать код в соответствующем компиляторе C, найдет его.

*arr2D и arr2D[0], однако, всегда эквивалентны, согласно определению оператора [].

То, что печатает код, можно только догадываться, поскольку код, содержащий нарушения ограничений, следует рассматривать как имеющий неопределенное поведение.

0 голосов
/ 27 августа 2018

Если мы вытянем ваш массив на «бумаге», он будет выглядеть так:

+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
| arr2D[0][0] | arr2D[0][1] | arr2D[0][2] | arr2D[1][0] | arr2D[1][1] | arr2D[1][2] | arr2D[2][0] | arr2D[2][1] | arr2D[2][2] |
+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+

Тогда вы должны помнить, что массив естественным образом распадается на указатель на свой первый элемент.Это просто arr2D, когда ожидается указатель, то же самое, что и &arr2D[0].

Теперь, если мы «перерисовываем» массив, но только для arr2D[0] (что является наиболее важным для вашеговопрос) с некоторыми из возможных указателей:

+-------------+-------------+-------------+-----+
| arr2D[0][0] | arr2D[0][1] | arr2D[0][2] | ... |
+-------------+-------------+-------------+-----+
^
|
&arr2D[0]
|
&arr2D[0][0]

Поскольку мы знаем, что arr2D совпадает с &arr2D[0], мы можем выполнить эту замену в выражении arr2D == *arr2D.Это заставляет нас &arr2D[0] == *&arr2D[0].

Операции разыменования * и address-of & отменяют друг друга, поэтому у нас есть &arr2D[0] == arr2D[0].

Теперь продолжайте в том же духе ...Мы знаем, что массив распадается на указатель на свой первый элемент, и мы знаем, что arr2D[0] является массивом;Это означает, что оно уменьшится до &arr2D[0][0], оставив нас с выражением &arr2D[0] == &arr2D[0][0].И как показано, эти два адреса одинаковы, что означает, что сравнение будет истинным.

Важное примечание: Хотя &arr2D[0] и &arr2D[0][0] могут оба указыватьв том же месте их типы различны.Тип &arr2D[0] равен int (*)[3], в то время как &arr2D[0][0] относится к типу int *.


Вооружившись приведенной выше информацией, следует легко расшифровать другое сравнение *arr2D == arr2D[0], особеннопоскольку все части этого уже упомянуты.

...