Примечание &arr
является полным 3-мерным массивом массива символов, тогда как arr
указывает на первый элемент, который представляет собой двумерный массив символов.Нечто, как показано ниже на схеме:
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]
, что это адрес полукокса 3D-массив размерности [5][7][6]
. Значительная разница между &arr
и &arr + 1
составляет 5 * 7 * 6 * sizeof(char)
= 210
.
Поскольку размер char[5][7][6]
составляет 5 * 7 * 6 * sizeof(char)
.
В вашем коде &arr
указывает на 3-мерный массив и &arry + 1
следующий 3-D массив (который не существует в нашем коде).
Проверить этот рабочий код на 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);
Вы до приведения типов значение без знака (но не в качестве адреса/тип указателя). Разница между 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
разница между Take (arr + 1) - (arr)
= 0xbf4836a8
- 0xbf48367e
= 0x2a
= 42
.
Последний Printf:
printf("%d\n", (unsigned)(p + 1) - (unsigned)p);
Просто разница между &arr+1
и &arr
= 210
(аналогично второму Printf), потому что p
является указателем на 3-D массив символов (= &arr
). И вы приписываете его типу значения (не указательному типу).
Кроме того, (Просто добавить для понимания цели, я предполагаю, что читатель найдет это полезным),
Давайте мы узнаем еще одно различие между arr
и &arr
с помощью оператора SizeOf, который поможет вашей понять концепцию более глубокое , Для первого чтения: sizeof
Operator
При применении оператора 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
это просто адрес, а в адрес системы имеет четыре байта и это адрес полного 3-мерного массива символов.
arr
- это имя 3-мерного массива, а оператор sizeof
дает общий размер массива 210 = 5 * 7 * 6 * sizeof(char)
.
Как я показал в моей диаграмме arr
указует на первые элементы, который является 2-мерным массивом. Так, потому что 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
Подсказка: '6 * 7 = 42',' 5 * 7 * 6 = 210' –
@Armin Может объясните пожалуйста? – Alex
Еще один намек - вы не конвертируете адрес в другой тип до тех пор, пока * после * вы уже сделали арифметику на указателях, которая выполняется в предположении исходного типа, а не окончательного типа ... – twalberg