[英]Passing 2D arrays in C
我从C中断了一次,只是又重新回到了C。
如果我想创建一个2D的双精度数组,我可以通过两种方式做到这一点:
double** m_array = (double**) malloc(2*sizeof(double*));
double* m_array = (double*) malloc(2*sizeof(double));
要么
double array[2][2];
但是,当我希望传递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])
首先,我不需要任何信息,它是指向指针数组的指针。 但是它只能是一个malloc数组。
在第二个中,我需要传递double *数组所指向的每个数组的长度。 这似乎很愚蠢。
我想念什么吗? 提前致谢。
第一个根本不创建二维数组。 它创建一个指针数组,该指针显然没有指向。 如果确实将每个指针初始化为一个数组,则该指针仍将是数组的数组,而不是二维数组。
为什么不创建二维数组呢?
double* dynamicArray = malloc(rows * columns * sizeof (double));
要么
double autoArray[rows][columns];
然后您可以使用以下任一功能:
void func(double* array, size_t rows, size_t columns);
为了澄清起见,假设您声明:
int my_static_array[row][col];
在pmg的答案中,my_static_array与malloc'd数组(称为my_malloc数组)的类型是什么? my_static_array是内存中连续的row * col * sizeof(int)个字节,并带有指向其开头的int *指针。 在计算my_static_array [x] [y]时,编译器会知道这样做(因为它们以行优先顺序存储):
*(addr(my_static_array) + [sizeof(int)*col*x] + [sizeof(int)*y])
这就是为什么我需要传递C的col值的原因:
(1) func(int my_static_array[][col])
(2) func(int my_static_array[][])
在(1)中,编译器知道如何为静态数组正确计算地址。 在(2)中,编译器没有足够的信息。 这就是为什么(1)编译而(2)不会编译的原因。
如果是malloc数组,则可以通过:
func(int** my_malloc_array)
由于它是指向一维数组的连续数组的指针,因此编译器不需要帮助。 my_malloc_array [x] [y]很简单:
*(*(addr(my_malloc_array)+x)+y)
编译器不需要其他有关其维数的信息即可进行计算。
那么,这是什么教训? 二维阵列是不一样的指针数组至1D阵列。 前者的类型为int(* my_static_array)[row * col]-指向行* col元素数组的指针,后者的类型为int **-指向行指针数组的指针。
您对2D阵列的分配是错误的。 通常的2D方法是
double **m_array = malloc(NROWS * sizeof *m_array);
for (i = 0; i < NROWS; i++) {
m_array[i] = malloc(NCOLS * sizeof *m_array[i]);
}
将数组或指针(任何维)传递给函数时,必须让函数知道维:它们未在数组或指针本身内编码。
一方面,您具有指向某些对象的指针(指向指针(至指针(...))),另一方面,您具有某种类型的数组(数组(属于数组(...)))。
当您将指针传递给函数时,就是这样。 当您“传递数组”时,发生的事情是该数组衰减为指向其第一个元素的指针。 所以
foo(array); // is the same as foo(&(array[0]));
当array
是多维数组时,衰减指针的类型是pointer to array[size] of SOMETHING
(但您不能使用该大小!)。
最简单的方法是使用简单的指针编写函数并传递所有维的乘法
double array[3][4][5];
foo(&(array[0][0][0]), 3*4*5);
假设计算机存储器是一个充满按顺序编号的框的仓库。 当你做
int matrix[10][3];
您保留30个用于保存矩阵值的框(例如,框131至160)。
现在,假设您要对函数中矩阵中的所有值求和:
int matrix_sum(int matrix[10][3]) { /* ... */ }
但是接收到的所有函数(由标准规定)都是指向矩阵第一个元素的指针:指向3个int
数组的指针。 因此,该函数知道框131、132和133属于矩阵,但它不知道矩阵实际有多长时间。
使用简单的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.