Могу ли я в C использовать передать многомерный массив для функции как единственный аргумент, если я не знаю, каковы будут размеры массива?
Кроме того, мой многомерный массив может содержать типы, отличные от строк.





Вы можете сделать это с любым типом данных. Просто сделайте это указателем на указатель:
typedef struct {
int myint;
char* mystring;
} data;
data** array;
Но не забывайте, что вам все равно нужно выполнить malloc для переменной, и это становится немного сложнее:
//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 () и т. д., Потому что память не выделяется в соседних ячейках памяти, что требуется для массивов. Ваша таблица поиска довольно разбросана по всей куче, что замедляет поиск и фрагментирует кучу.
Передайте явный указатель на первый элемент с размерами массива в качестве отдельных параметров. Например, для обработки двумерных массивов произвольного размера 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].
каковы значения i и j?
int matmax(int **p, int dim) // p- matrix , dim- dimension of the matrix
{
return p[0][0];
}
int main()
{
int *u[5]; // will be a 5x5 matrix
for(int i = 0; i < 5; i++)
u[i] = new int[5];
u[0][0] = 1; // initialize u[0][0] - not mandatory
// put data in u[][]
printf("%d", matmax(u, 0)); //call to function
getche(); // just to see the result
}
Это не 2D-массив, это таблица поиска. Кроме того, это помечено C.
Вы можете объявить свою функцию как:
f(int size, int data[][size]) {...}
Затем компилятор выполнит за вас всю арифметику с указателями.
Обратите внимание, что размеры размеров должны отображаться перед самого массива.
GNU C позволяет пересылку объявления аргументов (если вам действительно нужно передать размеры после массива):
f(int size; int data[][size], int size) {...}
Первое измерение, хотя вы также можете передать его в качестве аргумента, бесполезно для компилятора C (даже для оператора sizeof, когда он применяется к массиву, переданному как аргумент, он всегда будет рассматриваться как указатель на первый элемент).
ИМО, это должен быть принятый ответ. Никакого дополнительного кода и ненужного выделения кучи. простой и чистый
Спасибо @kjh, я тоже считаю, что это самое чистое решение. Принятый ответ - тот, который у него сработал. Смотрите: ОП от 2008 года, почти за 6 лет до моего ответа. Кроме того, я не знаю, допускали ли тогда стандарты C синтаксис, который я использовал здесь.
Это решение, которое я наконец принял для передачи целочисленной матрицы (двумерного массива) размера M x N в качестве аргумента функции. Возможно, будет полезно немного больше информации: Прототип функции похож на: void f (int N, int data [] [N], int M); В теле функции элемент [m] [n] может быть записан как data [m] [n] - очень удобно, вычисление индекса не требуется.
Я объявляю функцию, как вы сказали, я вызываю ее из main (), и все в порядке, но как мне объявить переменную data в моем main (), если я не знаю размер (а)? Я пробовал с int* data, но не работает.
@ glc78 Либо как VLA в стеке int data[height][width];, либо в куче с int (*data)[width] = malloc(height*sizeof(*data));. В обоих случаях вы можете впоследствии получить доступ к data[y][x] обычным способом и передать его f(width, data).
In C can I pass a multidimensional array to a function as a single argument when I don't know what the dimensions of the array are going to be?
Нет
Если под «одним аргументом» вы подразумеваете передачу только массива без передачи размеров массива, нет, вы не можете. По крайней мере, не для настоящих многомерных массивов.
Вы можете поместить измерение [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 );
Точно так же 3-мерный массив, например, 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 имеет значение sentinel, которое может использоваться для обозначения конца последнего одномерного массива нижнего уровня типа 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++;
}
}
здесь нужна помощь: stackoverflow.com/questions/16943909/…