В C могу ли я передать многомерный массив в функцию в качестве одного аргумента, если я не знаю, каковы будут размеры массива?
Кроме того, мой многомерный массив может содержать типы, отличные от строк.
В C могу ли я передать многомерный массив в функцию в качестве одного аргумента, если я не знаю, каковы будут размеры массива?
Кроме того, мой многомерный массив может содержать типы, отличные от строк.
Вы можете сделать это с любым типом данных. Просто сделайте его указателем на указатель:
typedef struct {
int myint;
char* mystring;
} data;
data** array;
Но не забывайте, что вам все еще нужно выделить переменную, и это становится немного сложным:
//initialize
int x,y,w,h;
w = 10; //width of array
h = 20; //height of array
//malloc the 'y' dimension
array = malloc(sizeof(data*) * h);
//iterate over 'y' dimension
for(y=0;y<h;y++){
//malloc the 'x' dimension
array[y] = malloc(sizeof(data) * w);
//iterate over the 'x' dimension
for(x=0;x<w;x++){
//malloc the string in the data structure
array[y][x].mystring = malloc(50); //50 chars
//initialize
array[y][x].myint = 6;
strcpy(array[y][x].mystring, "w00t");
}
}
Код для освобождения структуры выглядит аналогично — не забудьте вызвать free() для всего, что вы выделили! (Кроме того, в надежных приложениях следует проверить возврат функции malloc(). .)
Теперь предположим, что вы хотите передать это функции. Вы все еще можете использовать двойной указатель, потому что вы, вероятно, хотите выполнять манипуляции со структурой данных, а не с указателем на указатели структур данных:
int whatsMyInt(data** arrayPtr, int x, int y){
return arrayPtr[y][x].myint;
}
Вызовите эту функцию с помощью:
printf("My int is %d.\n", whatsMyInt(array, 2, 4));
Вывод:
My int is 6.
[][], он не превращается волшебным образом в массив. Вы не можете memcpy() и т. д., потому что память не выделяется в соседних ячейках памяти, что требуется для массивов. Ваша таблица поиска довольно разбросана по всей куче, что делает поиск медленным, а куча фрагментирована.
- person Lundin; 23.06.2015
Передайте явный указатель на первый элемент с размерами массива в качестве отдельных параметров. Например, для обработки двумерных массивов произвольного размера int:
void func_2d(int *p, size_t M, size_t N)
{
size_t i, j;
...
p[i*N+j] = ...;
}
который будет называться
...
int arr1[10][20];
int arr2[5][80];
...
func_2d(&arr1[0][0], 10, 20);
func_2d(&arr2[0][0], 5, 80);
Тот же принцип применяется для массивов более высокой размерности:
func_3d(int *p, size_t X, size_t Y, size_t Z)
{
size_t i, j, k;
...
p[i*Y*Z+j*Z+k] = ...;
...
}
...
arr2[10][20][30];
...
func_3d(&arr[0][0][0], 10, 20, 30);
p[i*Y+j*Z+k] должно быть p[i*Y*Z+j*Z+k].
- person David H; 18.08.2012
Вы можете объявить свою функцию как:
f(int size, int data[][size]) {...}
Затем компилятор сделает всю арифметику указателя за вас.
Обратите внимание, что размеры размеров должны стоять перед самим массивом.
GNU C позволяет пересылать объявления аргументов (на случай, если вам действительно нужно передать размеры после массива):
f(int size; int data[][size], int size) {...}
Первое измерение, хотя вы также можете передать его в качестве аргумента, бесполезно для компилятора C (даже для оператора sizeof, когда он применяется к массиву, переданному в качестве аргумента, всегда будет рассматриваться как указатель на первый элемент).
data в моей main(), если я не знаю размеров? Я пытался с int* data, но не работает.
- person glc78; 27.08.2017
int data[height][width];, либо в куче с int (*data)[width] = malloc(height*sizeof(*data));. В обоих случаях вы можете впоследствии получить доступ к data[y][x] обычным способом и передать его f(width, data).
- person cmaster - reinstate monica; 13.12.2019
В C могу ли я передать многомерный массив функции в качестве одного аргумента, когда я не знаю, каковы будут размеры массива?
Нет
Если под «одним аргументом» вы подразумеваете передачу только массива без передачи размеров массива, вы не можете. По крайней мере, не для настоящих многомерных массивов.
Вы можете поместить измерение [s] в структуру вместе с массивом и заявить, что передаете «один аргумент», но на самом деле это просто упаковка нескольких значений в один контейнер и вызов этого контейнера «один аргумент».
Вы можете передать массив известного типа и количества измерений, но неизвестного размера, передав сами измерения и массив следующим образом:
void print2dIntArray( size_t x, size_t y, int array[ x ][ y ] )
{
for ( size_t ii = 0, ii < x; ii++ )
{
char *sep = "";
for ( size_t jj = 0; jj < y; jj++ )
{
printf( "%s%d", sep, array[ ii ][ jj ] );
sep = ", ";
}
printf( "\n" );
}
}
Вы бы назвали эту функцию следующим образом:
int a[ 4 ][ 5 ];
int b[ 255 ][ 16 ];
...
print2dIntArray( 4, 5, a );
....
printt2dIntArray( 255, 16, b );
Точно так же трехмерный массив, например, struct pixel:
void print3dPixelArray( size_t x, size_t y, size_t z, struct pixel pixelArray[ x ][ y ][ z ] )
{
...
}
или одномерный массив double:
void print1dDoubleArray( size_t x, double doubleArray[ x ] )
{
...
}
НО...
Однако можно передавать «массивы указателей на массивы указателей на... массив типа X», которые часто ошибочно называют «многомерным массивом», в качестве одного аргумента, если базовый тип X имеет сигнальное значение, которое можно использовать для указания конца конечного одномерного массива самого низкого уровня типа X.
Например, значение char **argv, переданное в main(), является указателем на массив указателей на char. Исходный массив из char * указателей заканчивается NULL сигнальным значением, а каждый массив char, на который ссылается массив из char * указателей, заканчивается NUL символьным значением '\0'.
Например, если вы можете использовать NAN в качестве контрольного значения, поскольку фактические данные никогда не будут равны NAN, вы можете напечатать double ** следующим образом:
void printDoubles( double **notAnArray )
{
while ( *notAnArray )
{
char *sep = "";
for ( size_t ii = 0; ( *notAnArray )[ ii ] != NAN; ii++ )
{
printf( "%s%f", sep, ( *notAnArray )[ ii ] );
sep = ", ";
}
notAnArray++;
}
}