Ответ 1
Примечание &arr
- это полный 3-мерный адрес массива char, тогда как arr
указывает на первый элемент, который является двумерным массивом char. Что-то вроде ниже в диаграмме:
0xbf8ce2c6
+------------------+ ◄-- arr = 0xbf8ce2c6
| 0xbf8ce2f0 |
| +------------------+ ◄-- arr + 1 = 0xbf8ce2f0
| | 0xbf8ce31a | |
| | +------------------+ ◄-- arr + 2 = 0xbf8ce31a
| | 0xbf8ce344 | | |
| | | +------------------+ ◄-- arr + 3 = 0xbf8ce344
| | 0xbf8ce36e | | | |
| | | | +------------------+ ◄-- arr + 4 = 0xbf8ce36e
| | | | | | | | | |
+---|---|---|--|---+ | | | | Each are 7*6, 2-Dimensional
| | | | | | | | Consists Of 42 bytes
+---|---|--|-------+ | | |
| | | | | |
+---|--|-----------+ | |
| | | |
+--|---------------+ |
| |
+------------------+
The diagram show:
1. How a 3-dimensional can be interpreted as series of 2-dimensional arrays
2. Here (arr + i) points to a 2-D array
3. Notice difference between: (arr + i + 1) - (arr + i) = 0x2a = 42, where i = [0, 4]
Тип &arr
- char(*)[5][7][6]
, который является адресом char 3D-массива измерения [5][7][6]
.
Значительная разница между &arr
и &arr + 1
равна 5 * 7 * 6 * sizeof(char)
= 210
.
Поскольку размер char[5][7][6]
равен 5 * 7 * 6 * sizeof(char)
.
В вашем коде &arr
указывается на трехмерный массив и &arry + 1
следующий трехмерный массив (который не существует в нашем коде).
Проверьте этот рабочий код на codepade:
int main()
{
char arr[5][7][6];
printf(" &arr : %p", &arr);
printf(" &arr+1: %p", &arr + 1);
return 0;
}
Выход:
&arr : 0xbf5dd7de
&arr+1: 0xbf5dd8b0
Разница между (&arr + 1) - (&arr)
= 0xbf5dd8b0 - 0xbf5dd7de
= 0xd2
= 210
.
Во втором printf:
printf("%d\n", (char *)(&arr + 1) - (char *)&arr);
Вы присваиваете адреса типам char(*)[5][7][6]
равным (char*)
, а поскольку sizeof char[5][7][6]
210
, оба адреса 210 далеки. (помните sizeof(char) == 1
). Это причина выхода: 210
Теперь, как я сказал в первом утверждении, arr
- это адрес первого элемента, который представляет собой двумерный массив символов. Тип arr
- char(*)[7][6]
. Теперь один элемент (двумерный массив размера 6 * 7 * sizeof(char) = 42
).
(Примечание: вы можете представить трехмерный массив в виде массива один-d, где каждый элемент представляет собой 2-мерный массив).
В третьей версии printf:
printf("%d\n", (unsigned)(arr + 1) - (unsigned)arr);
Вы присваиваете значения методу unsigned (но не к типу адреса/указателя). Разница между arr + 1
и arr
равна 42 * sizeof(char)
= 42
(то есть равна размеру char[7][6]
). Поэтому вывод printf: 42
.
Примечание. Вы должны читать sizeof (int) == sizeof (void *)?, потому что вы указываете адрес для значения. и это преобразование не полностью определено. (мое объяснение касается вашего вывода и результата, который я дал).
Для дальнейшего уточнения проверьте ниже рабочий код codepade:
int main()
{
char arr[5][7][6];
printf(" arr : %p\n", arr);
printf(" arr+1: %p", arr + 1);
return 0;
}
Выход:
arr : 0xbf48367e
arr+1: 0xbf4836a8
Сделайте разницу между (arr + 1) - (arr)
= 0xbf4836a8
- 0xbf48367e
= 0x2a
= 42
.
Последний printf:
printf("%d\n", (unsigned)(p + 1) - (unsigned)p);
Просто используйте разницу между &arr+1
и &arr
= 210
(аналогично второй printf), потому что p
является указателем на 3-D char array (= &arr
). И вы приписываете его типу значения (не указательному типу).
Кроме того, (просто добавляя для понимания цели, я думаю, читатель найдет это полезным),
Давайте узнаем еще одно различие между arr
и &arr
, используя оператор sizeof, который поможет вам глубже понять концепцию. Для этого сначала читайте: sizeof
Оператор
Когда вы применяете оператор
sizeof
к идентификатору массива, результатом является размер всего массива, а не размер указателя, представленный идентификатором массива.
Проверьте этот рабочий код на codepade:
int main()
{
char arr[5][7][6];
printf(" Sizeof(&arr) : %lu and value &arr: %p\n", sizeof(&arr), &arr);
printf(" Sizeof(arr) : %lu and value arr : %p\n", sizeof(arr), arr);
printf(" Sizeof(arr[0]): %lu and value a[0]: %p\n",sizeof(arr[0]), arr[0]);
return 0;
}
Его вывод:
Sizeof(&arr) : 4 and value &arr: 0xbf4d9eda
Sizeof(arr) : 210 and value arr : 0xbf4d9eda
Sizeof(arr[0]): 42 and value a[0]: 0xbf4d9eda
-
Здесь
&arr
- это просто адрес, а в системном адресе - четыре байта, и это адрес полного трехмерного массива char. -
arr
- это имя 3-мерного массива, а операторsizeof
дает общий размер массива210 = 5 * 7 * 6 * sizeof(char)
.
Как я показал на моей диаграмме arr
, указывает на первые элементы, являющиеся двумерным массивом. Поэтому, поскольку arr
= (arr + 0)
. Теперь с помощью *
Оператор разыменования в (arr + 0)
дает значение по адресу так *(arr + 0) = arr[0]
.
- Примечание
sizeof(arr[0])
дает42
=7 * 6 * sizeof(char)
. И это доказательство концептуально представляет собой трехмерный массив, но массив двумерного массива.
Потому что выше в моем ответе много раз я писал: "размер char[5][7][6]
- 5 * 7 * 6 * sizeof(char)
". поэтому я добавляю интересный код ниже @codepade:
int main(){
printf(" Char : %lu \n", sizeof(char));
printf(" Char[5] : %lu \n", sizeof(char[6]));
printf(" Char[5][7] : %lu \n", sizeof(char[7][6]));
printf(" Char[5][7][6]: %lu \n", sizeof(char[5][7][6]));
return 1;
}
Вывод:
Char : 1
Char[5] : 6
Char[5][7] : 42
Char[5][7][6]: 210