简体   繁体   English

在C中传递2D数组

[英]Passing 2D arrays in C

I took a hiatus from C and am just getting back into it again. 我从C中断了一次,只是又重新回到了C。

If I want to create a 2D array of doubles, I can do it two ways: 如果我想创建一个2D的双精度数组,我可以通过两种方式做到这一点:

double** m_array = (double**) malloc(2*sizeof(double*));
double*  m_array = (double*)  malloc(2*sizeof(double));

OR 要么

double array[2][2];

But, when I wish to pass the malloc'd array versus passing the other, there seems to be two conventions: 但是,当我希望传递malloc数组而不是传递另一个数组时,似乎有两个约定:

//allowed for passing in malloc'd array, but not for other array
func_m(m_array) //allowed
func_m(array) //disallowed
func_m(double** m_array)

//allowed for passing in either array; required for passing in non-malloc'd array
func(m_array) //allowed
func(array) //allowed
func(double array[][2])

In the first, I don't need any information beyond that it is a pointer to an array of pointers. 首先,我不需要任何信息,它是指向指针数组的指针。 But it can only be a malloc'd array. 但是它只能是一个malloc数组。

In the second, I need to pass the length of each array that the array of double* points to. 在第二个中,我需要传递double *数组所指向的每个数组的长度。 This seems silly. 这似乎很愚蠢。

Am I missing something? 我想念什么吗? Thanks in advance. 提前致谢。

The first one doesn't create a 2-D array at all. 第一个根本不创建二维数组。 It creates an array of pointers, which apparently point nowhere. 它创建一个指针数组,该指针显然没有指向。 If you did initialize each pointer to be an array, that would still be an array of arrays, not a 2-D array. 如果确实将每个指针初始化为一个数组,则该指针仍将是数组的数组,而不是二维数组。

Why don't you just create a 2-D array? 为什么不创建二维数组呢?

double* dynamicArray = malloc(rows * columns * sizeof (double));

or 要么

double autoArray[rows][columns];

and then you can use either one with this function: 然后您可以使用以下任一功能:

void func(double* array, size_t rows, size_t columns);

For clarification, suppose you declare: 为了澄清起见,假设您声明:

int my_static_array[row][col];

What is the type of my_static_array vs the malloc'd array (let's call it my_malloc array) in pmg's answer? 在pmg的答案中,my_static_array与malloc'd数组(称为my_malloc数组)的类型是什么? my_static_array is a contiguous row*col*sizeof(int) number of bytes in memory, with an int* pointer to its beginning. my_static_array是内存中连续的row * col * sizeof(int)个字节,并带有指向其开头的int *指针。 When computing my_static_array[x][y], the compiler knows to do (because they are stored in row-major order ): 在计算my_static_array [x] [y]时,编译器会知道这样做(因为它们以行优先顺序存储):

*(addr(my_static_array) + [sizeof(int)*col*x] + [sizeof(int)*y])

This is why I need to pass in the col value for C: 这就是为什么我需要传递C的col值的原因:

(1) func(int my_static_array[][col])
(2) func(int my_static_array[][])

In (1), the compiler knows how to compute the address properly for the static array. 在(1)中,编译器知道如何为静态数组正确计算地址。 In (2), the compiler does not have enough information. 在(2)中,编译器没有足够的信息。 This is why (1) compiles, and (2) will not. 这就是为什么(1)编译而(2)不会编译的原因。

If it is the malloc'd array, however, one can pass: 如果是malloc数组,则可以通过:

func(int** my_malloc_array)

Since it is a pointer to a contiguous array of 1D arrays, the compiler needs no help. 由于它是指向一维数组的连续数组的指针,因此编译器不需要帮助。 my_malloc_array[x][y] is done simply: my_malloc_array [x] [y]很简单:

*(*(addr(my_malloc_array)+x)+y)

The compiler needs no other information about its dimensionality in order to compute. 编译器不需要其他有关其维数的信息即可进行计算。

So, what is the lesson? 那么,这是什么教训? 2D arrays are NOT the same as an array of pointers to 1D arrays. 二维阵列是一样的指针数组至1D阵列。 The former has type int (*my_static_array)[row*col] -- pointer to an array of row*col elements, the latter has type int** -- pointer to an array of row pointers. 前者的类型为int(* my_static_array)[row * col]-指向行* col元素数组的指针,后者的类型为int **-指向指针数组的指针。

Your allocation for the 2D array is wrong. 您对2D阵列的分配是错误的。 The usual 2D way is 通常的2D方法是

double **m_array = malloc(NROWS * sizeof *m_array);
for (i = 0; i < NROWS; i++) {
  m_array[i] = malloc(NCOLS * sizeof *m_array[i]);
}

When passing arrays or pointers (any dimensions) to functions you have to let the function know the dimensions: they are not encoded within the array or pointers themselves. 将数组或指针(任何维)传递给函数时,必须让函数知道维:它们未在数组或指针本身内编码。

On one hand, you have pointers (to pointers (to pointers (...))) to some and on the other hand you have arrays (of arrays (of arrays (...))) of some type. 一方面,您具有指向某些对象的指针(指向指针(至指针(...))),另一方面,您具有某种类型的数组(数组(属于数组(...)))。

When you pass a pointer to a function, that's exactly what happens. 当您将指针传递给函数时,就是这样。 When you "pass an array", what happens is that the array decays into a pointer to its first element. 当您“传递数组”时,发生的事情是该数组衰减为指向其第一个元素的指针。 So 所以

foo(array); // is the same as foo(&(array[0]));

and when array is a multidimensional array the type of the decayed pointer is pointer to array[size] of SOMETHING (but you can't use that size!). array是多维数组时,衰减指针的类型是pointer to array[size] of SOMETHING (但您不能使用该大小!)。

The easy way out is to write your functions with a simple pointer and pass the multiplication of all dimensions 最简单的方法是使用简单的指针编写函数并传递所有维的乘法

double array[3][4][5];
foo(&(array[0][0][0]), 3*4*5);

Suppose the computer memory is a warehouse full of sequentially numbered boxes. 假设计算机存储器是一个充满按顺序编号的框的仓库。 When you do 当你做

int matrix[10][3];

you reserve 30 boxes for holding matrix values (let's say boxes 131 to 160 inclusive). 您保留30个用于保存矩阵值的框(例如,框131至160)。

Now, lets say you want to sum all the values in the matrix in a function: 现在,假设您要对函数中矩阵中的所有值求和:

int matrix_sum(int matrix[10][3]) { /* ... */ }

but all the function receives (mandated by the Standard) is a pointer to the first element of matrix: a pointer to an array of 3 int s. 但是接收到的所有函数(由标准规定)都是指向矩阵第一个元素的指针:指向3个int数组的指针。 So the function knows boxes 131, 132, and 133 belong to the matrix, but it doesn't know how long the matrix really is. 因此,该函数知道框131、132和133属于矩阵,但它不知道矩阵实际有多长时间。

Use a simple typedef: 使用简单的typedef:

typedef double Twodouble_t[2];

void func(Twodouble_t *ptr)
{
  size_t i, numelements = sizeof*ptr/sizeof**ptr;
  puts("first array");
  for( i=0; i<numelements; ++i )
    printf("\n%f",ptr[0][i]);
}
...
Twodouble_t array[]={ {1., 1.},{2., 2.},{3.,3.} };
func(array);
...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM