char t[N][N];
фактически совпадает с
char t[N * N];
в памяти.Указатель на такой массив в обоих случаях будет иметь тип char *
.
char ***
- указатель на указатель, то есть указатель на символ, тогда как char *
- указатель наchar и вот как вы передаете ссылки на массивы в C: вы передаете их как указатель на первый элемент этого массива, и этот первый элемент является char.
C не может сохранить точный тип или структуру массива каккак только вы передадите его функциям.В памяти массив символов - это просто набор памяти, заполненный символами, и все, что вы можете передать, - это указатель на эту память.Если эта память char []
или char [][]
или даже char [][][]
не играет никакой роли, в памяти все три представляют собой блок, полный символов, и функция должна была бы явно знать структуру в памяти, в противном случае все массивы символов всегда будутchar []
для функции.
Я настоятельно рекомендую новичкам в C использовать многомерные массивы.Вместо
char t[N][N];
char c = t[y1][x1];
t[y2][x2] = 'X';
используйте
char t[N];
char c = t[y1 * N + x1];
t[y2 * N + x2] = 'X';
Так как это в основном то, что компилятор все равно будет делать внутри.
Обратите внимание, что многомерные массивы в C не xy, а yxпервое значение - это строка, второе - в столбце. см. этот урок .
Кто не поверит тому, что я только что сказал, попробуйте этот код:
int main ( ) {
char a[5][5];
for (int y = 0; y < 5; y++) {
for (int x = 0; x < 5; x++) {
a[y][x] = x + 10 * y;
}
}
for (int y = 0; y < 5; y++) {
for (int x = 0; x < 5; x++) {
printf("%02d ", a[y][x]);
}
printf("\n");
}
printf("------\n");
char * a2 = (char *)a;
for (int y = 0; y < 5; y++) {
for (int x = 0; x < 5; x++) {
printf("%02d ", a2[y * 5 + x]);
}
printf("\n");
}
}
Вы можете запустить его онлайн , если хотите, вывод идентичен.Также взгляните на ассемблерный код, сгенерированный компилятором для любого цикла (например, gcc -S
), и вы увидите, что он почти идентичен, поскольку даже в первом случае компилятор использует инструкции add
и mul
для доступа к правильномуячейка памяти в массиве.