ПРИМЕЧАНИЕ. Намерение примеров, используемых в этом сообщении, - это просто объяснение понятий. Таким образом, примеры могут быть неполными, могут отсутствовать обработка ошибок и т. Д.
Когда дело доходит до использования многомерного массива в C
, возможны два возможных способа.
Сведение массивов
В C
массивы реализованы в виде непрерывного блока памяти. Эта информация может использоваться для управления значениями, хранящимися в массиве, и обеспечивает быстрый доступ к определенному местоположению массива.
Например,
int arr[10][10];
int *ptr = (int *)arr ;
ptr[11] = 10;
// this is equivalent to arr[1][0] = 10; assign a 2D array
// and manipulate now as a single dimensional array.
Методика использования непрерывной природы массивы известен как flattening of arrays
.
Рваные Массивы
Теперь рассмотрим следующий пример.
char **list;
list[0] = "United States of America";
list[1] = "India";
list[2] = "United Kingdom";
for(int i=0; i< 3 ;i++)
printf(" %d ",strlen(list[i]));
// prints 24 5 14
Этот тип реализации известен как оборванный массив и полезен в тех местах, где используются строки переменного размера. Популярный метод состоит в том, чтобы сделать dynamic-memory-allocation
для каждого измерения.
ПРИМЕЧАНИЕ: Аргумент командной строки (char *argv[]
) передается только как оборванный массив.
Сравнивая плоские и неровные массивы
Теперь давайте рассмотрим следующий фрагмент кода, который сравнивает flattened
и ragged
массивы.
/* Note: lacks error handling */
int flattened[30][20][10];
int ***ragged;
int i,j,numElements=0,numPointers=1;
ragged = (int ***) malloc(sizeof(int **) * 30);
numPointers += 30;
for(i=0; i<30; i++) {
ragged[i] = (int **)malloc(sizeof(int*) * 20);
numPointers += 20;
for(j=0; j<20; j++) {
ragged[i][j]=(int*)malloc(sizeof(int) * 10);
numElements += 10;
}
}
printf("Number of elements = %d",numElements);
printf("Number of pointers = %d",numPointers);
// it prints
// Number of elements = 6000
// Number of pointers = 631
Из приведенного выше примера, в ragged
массивы требуют 631-pointers
, другими словами, 631 * sizeof(int *)
дополнительные ячейки памяти для указывая 6000
целых чисел. В то время как для массива flattened
требуется только один базовый указатель: т. Е. Имя массива достаточно, чтобы указывать на смежные ячейки памяти 6000
.
Но OTOH, массивы ragged
являются гибкими. В случаях, когда точное количество требуемых мест памяти неизвестно, вы не можете позволить себе распределить память для наихудшего возможного случая. Опять же, в некоторых случаях точное количество требуемого пространства памяти известно только во время выполнения. В таких ситуациях ragged
массивы становятся удобными.
Роу-мажор и столбцы из основных массивов
C
следующим образом row-major
упорядочения для многомерных массивов. Flattening
массивов можно рассматривать как эффект из-за этого аспекта в C
. Значение порядка в порядке его соответствия этому естественному способу, в котором большая часть доступа осуществляется в программировании. Например, давайте рассмотрим пример для обхода N * M
2D матрицу,
for(i=0; i<N; i++) {
for(j=0; j<M; j++)
printf(“%d ”, matrix[i][j]);
printf("\n");
}
Каждая строка в матрице доступен один за другим, меняя колонку быстро. Массив C
устроен в памяти естественным образом. Напротив, рассмотрим следующий пример:
for(i=0; i<M; i++) {
for(j=0; j<N; j++)
printf(“%d ”, matrix[j][i]);
printf("\n");
}
Это изменяет индекс столбца чаще, чем индекс строки. И из-за этого существует большая разница в эффективности между этими двумя фрагментами кода. Да, первый из них более эффективен, чем второй!
Потому что первый обращается к массиву в натуральном порядке (row-major
), поэтому он быстрее, тогда как второй занимает больше времени, чтобы прыгать. Разница в производительности будет расширяться по мере увеличения количества измерений и размера элемента.
Поэтому при работе с многоразмерными массивами в C
, полезно рассмотреть приведенные выше детали!
Что вы пытаетесь сделать с данными? Трудно сказать вам, что попробовать, не зная ничего о том, что вы делаете. – user1118321