Массив для затухания указателя и передачи многомерных массивов в функции

Я знаю, что массив распадается на указатель, так что если один объявил

char things[8];

а потом использовал things где-нибудь еще, things указатель на первый элемент в массиве

Кроме того, насколько я понимаю, если

char moreThings[8][8];

затем moreThings не имеет указатель типа на символ, но имеет тип "массив указателей на символ", потому что затухание происходит только один раз.

когда moreThings передается в функцию (скажем, с прототипом void doThings(char thingsGoHere[8][8]) что на самом деле происходит со стеком?

Если moreThings это не указатель типа, то действительно ли это все еще передача по ссылке? Я думаю, я всегда думал, что moreThings по-прежнему представляет базовый адрес многомерного массива. Что, если doThings принял вход thingsGoHere а сам передал это другой функции?

Является ли правило в значительной степени тем, что если не указать вход массива как const тогда массив всегда будет изменяемым?

Я знаю, что проверка типов происходит только во время компиляции, но я все еще не понимаю, что технически считается передачей по ссылке (т. Е. Происходит ли это только тогда, когда передаются аргументы указателя типа, или массив указателей будет проходным по ссылке тоже?)

Извините, что был немного повсюду с этим вопросом, но из-за моих трудностей в понимании этого трудно сформулировать точный вопрос.

3 ответа

Решение

Вы немного ошиблись moreThings также распадается на указатель на первый элемент, но так как это массив массива символов, первый элемент является "массивом из 8 символов". Таким образом, разрушенный указатель имеет такой тип:

char (*p)[8] = moreThings;

Значение указателя, конечно, совпадает со значением &moreThings[0][0], т.е. первого элемента первого элемента, а также того же самого &a, но тип отличается в каждом случае.

Вот пример, если char a[N][3]:

+===========================+===========================+====
|+--------+--------+-------+|+--------+--------+-------+|
|| a[0,0] | a[0,1] | a[0,2]||| a[1,0] | a[1,1] | a[1,2]|| ...
|+--------+--------+-------+++--------+--------+-------++ ...
|            a[0]           |            a[1]           |
+===========================+===========================+====
                                    a
^^^
||+-- &a[0,0]
|+-----&a[0]
+-------&a
  • &a: адрес всего массива массивов символов, который является char[N][3]

  • &a[0], такой же как a: адрес первого элемента, который сам по себе char[3]

  • &a[0][0]: адрес первого элемента первого элемента, который является char

Это демонстрирует, что разные объекты могут иметь один и тот же адрес, но если два объекта имеют один и тот же адрес и один и тот же тип, то это один и тот же объект.

"АДРЕС МАРШРУТА И УКАЗАТЕЛИ НА МНОГОМЕРНЫЕ МЕРЫ"

Давайте сначала начнем с 1-D массива:

  • декларация char a[8]; создает массив из 8 элементов.
    И здесь a это адрес первого элемента, но не адрес массива.

  • char* ptr = a; правильное выражение как ptr является указателем на символ и может адресовать первый элемент.

  • Но выражение ptr = &a это неправильно! Так как ptr не может обратиться к массиву.

  • & адрес средства массива. Действительно ценность a а также &a одинаковы, но семантически оба различны, один - адрес символа, другой - адрес массива из 8 символов.

  • char (*ptr2)[8]; Вот ptr2 is pointer to an array of 8 chars И на этот раз ptr2=&a является допустимым выражением.

  • Тип данных &a является char(*)[8] и тип a является char[8] это просто распадается в char* в большинстве операций, например char* ptr = a;

    Чтобы понять лучше читать: разница между char *str а также char str[] а как оба хранятся в памяти?

Второй случай,

  • декларация char aa[8][8]; создает двумерный массив 8x8 размер.

  • Любой двумерный массив также можно рассматривать как одномерный массив, в котором каждый элемент массива является одномерным массивом.

  • aa это адрес первого элемента, который является массивом из 8 символов. выражение ptr2 = aa является действительным и правильным.

  • Если мы объявим следующее:

    char (*ptr3)[8][8];    
    char ptr3 = &aa;  //is a correct expression
    

    Так же,
    moreThings в вашей декларации char moreThings[8][8]; содержит адрес первого элемента, который является массивом из 8 элементов.

    Чтобы понять лучше читать: разница между char* str[] а также char str[][] а как оба хранятся в памяти?


Было бы интересно узнать:

  • morething адрес массива из 8 символов

  • *morething это адрес первого элемента, который &morething[0][0],

  • &morething это адрес двумерного массива 8 х 8.

    И значения адресов всех трех выше одинаковы, но семантически все различны.

  • **morething это значение первого элемента, который morething[0][0],

    Чтобы понять лучше читать: разница между &str а также str , когда str объявлен как char str[10] ?

Дальше больше,

  • void doThings(char thingsGoHere[8][8]) не что иное, как пустота doThings(char (*thingsGoHere)[8]) и таким образом принимает любой массив, который является двумерным со вторым измерением, равным 8.

О типе переменных в C и C++: (Я хотел бы добавить в ответ)

  • Ничто не передается по ссылке в C его концепции C++. Если это используется в C, это означает, что автор говорит о переменной указателя.
  • C поддерживает pass by Address а также pass by value,
  • C++ поддерживает Pass by address, pass by value а также pass by Reference,

    Читайте: переменные указателя и ссылочные переменные

В конце,

  • Имя массива является постоянным идентификатором, а не переменным.

Хорошо объяснил Керрек,

В дополнение к этому мы можем доказать это на следующем примере:

#include <stdio.h>

int main ()
{
 int a[10][10];

 printf (".. %p  %p\n", &a, &a+1);
 printf (".. %p  %p \n ", &a[0], &a[0]+1);
printf (".. %p   %p \n ", &a[0][0], &a[0][0] +1);
}

Выход:

.. 0x7fff6ae2ca5c  0x7fff6ae2cbec    = 400 bytes difference
.. 0x7fff6ae2ca5c  0x7fff6ae2ca84    = 40 bytes difference
 .. 0x7fff6ae2ca5c   0x7fff6ae2ca60  = 4 bytes difference. 

& a +1 -> Перемещает указатель, добавляя весь размер массива. т.е. 400 байт

&a[0] + 1 -> Перемещает указатель, добавляя размер столбца. т.е. 40 байтов.

& a [0] [0] +1 -> Перемещает указатель, добавляя размер элемента, т.е. 4 байта.

[размер int 4 байта]

Надеюсь это поможет.:)

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