10x30:
int(*array)[30] = malloc((sizeof *array) * 10);
15x20:
int(*array)[20] = malloc((sizeof *array) * 15);
Изменение размера до 20x25:
int(*array2)[25] = realloc(array, (sizeof *array2) * 20);
Внешний размер (10, 15, 20) может бытьопределяется во время выполнения, потому что это не нужно как часть расчета индекса компилятором.Внутреннее измерение (30, 20, 25) должно быть известно во время компиляции.Надеюсь, поможет.
Обратите внимание, что в отличие от решений с массивом указателей, это может быть обработано как один блок памяти, поскольку оно распределяет все в одном куске памяти как настоящий объявленный массив:
memcpy(somewhere, array2, sizeof(int) * 20 * 25); // (sizeof *array2) * 20
Однако в конечном итоге это зависит от вашего варианта использования.
Поскольку некоторые люди испытывают трудности с пониманием действий, выполняемых индексной операцией для array
, давайте посмотрим, что Clang дает нам для выражения индекса вследующий код
int main() {
int(*array)[10] = malloc((sizeof *array) * 5);
array[4][9] = 0;
int(*array1)[10][5] = malloc((sizeof *array1) * 20);
array1[19][9][4] = 0;
}
Это хороший компилятор, который может печатать свои AST легко читаемым способом
// array[4][9] = 0;
(BinaryOperator 0xba62cc0 <line:5:3, col:17> 'int' '='
(ArraySubscriptExpr 0xba62c80 <col:3, col:13> 'int'
(ImplicitCastExpr 0xba62c60 <col:3, col:10> 'int *' <ArrayToPointerDecay>
(ArraySubscriptExpr 0xba62c20 <col:3, col:10> 'int [10]'
(DeclRefExpr 0xba62bdc <col:3> 'int (*)[10]' Var='array' 0xba62a00)
(IntegerLiteral 0xba62c00 <col:9> 'int' 4)))
(IntegerLiteral 0xba62c40 <col:12> 'int' 9))
(IntegerLiteral 0xba62ca0 <col:17> 'int' 0))
// array1[19][9][4] = 0;
(BinaryOperator 0xba630b8 <line:8:3, col:22> 'int' '='
(ArraySubscriptExpr 0xba63078 <col:3, col:18> 'int'
(ImplicitCastExpr 0xba63058 <col:3, col:15> 'int *' <ArrayToPointerDecay>
(ArraySubscriptExpr 0xba63018 <col:3, col:15> 'int [5]'
(ImplicitCastExpr 0xba62ff8 <col:3, col:12> 'int (*)[5]' <ArrayToPointerDecay>
(ArraySubscriptExpr 0xba62fa0 <col:3, col:12> 'int [10][5]'
(DeclRefExpr 0xba62f5c <col:3> 'int (*)[10][5]' Var='array1' 0xba62db0)
(IntegerLiteral 0xba62f80 <col:10> 'int' 19)))
(IntegerLiteral 0xba62fc0 <col:14> 'int' 9)))
(IntegerLiteral 0xba63038 <col:17> 'int' 4))
(IntegerLiteral 0xba63098 <col:22> 'int' 0)))
Обратите внимание, что каждое выражение индекса массива принимает указатель, добавляет значениеиндекс, и возвращает адресный элемент.Если этот подэлемент является массивом, он распадается на указатель на свой первый элемент.Это на самом деле не отличается от шагов, выполняемых для объявленного массива
int main() {
int array[5][10] = { };
array[4][9] = 1;
}
Получает очень похожий AST, причем только самое внутреннее выражение сначала распадается на указатель на его первый элемент
// array[4][9] = 1;
(BinaryOperator 0xbf9f7e8 <line:5:3, col:17> 'int' '='
(ArraySubscriptExpr 0xbf9f7a8 <col:3, col:13> 'int'
(ImplicitCastExpr 0xbf9f788 <col:3, col:10> 'int *' <ArrayToPointerDecay>
(ArraySubscriptExpr 0xbf9f748 <col:3, col:10> 'int [10]'
(ImplicitCastExpr 0xbf9f728 <col:3> 'int (*)[10]' <ArrayToPointerDecay>
(DeclRefExpr 0xbf9f6cc <col:3> 'int [5][10]' Var='array' 0xbfa81f0))
(IntegerLiteral 0xbf9f6f0 <col:9> 'int' 4)))
(IntegerLiteral 0xbf9f768 <col:12> 'int' 9))
(IntegerLiteral 0xbf9f7c8 <col:17> 'int' 1)))