0

我从 C 中断了一段时间,现在又回到了它。

如果我想创建一个二维数组,我可以通过两种方式进行:

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

或者

double array[2][2];

但是,当我希望传递 malloc'd 数组而不是传递另一个时,似乎有两个约定:

//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* 数组指向的每个数组的长度。这似乎很愚蠢。

我错过了什么吗?提前致谢。

4

5 回答 5

6

第一个根本不创建二维数组。它创建了一个指针数组,显然没有指向任何地方。如果您确实将每个指针初始化为一个数组,那仍然是一个数组数组,而不是二维数组。

为什么不直接创建一个二维数组?

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

或者

double autoArray[rows][columns];

然后您可以将其中任何一个与此功能一起使用:

void func(double* array, size_t rows, size_t columns);
于 2010-10-02T23:28:55.693 回答
2

为了澄清起见,假设您声明:

int my_static_array[row][col];

在 pmg 的答案中,my_static_array 与 malloc 数组(我们称之为 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)

编译器不需要关于其维度的其他信息来计算。

那么,教训是什么?二维数组与指向一维数组的指针数组不同。前者的类型为 int (*my_static_array)[row*col] - 指向row*col元素数组的指针,后者的类型为 int** - 指向指针数组的指针。

于 2010-10-03T06:46:52.283 回答
0

使用简单的 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);
...
于 2010-10-04T21:52:11.073 回答
0

您对二维数组的分配是错误的。通常的 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);
于 2010-10-02T23:41:15.060 回答
0

假设计算机内存是一个装满按顺序编号的盒子的仓库。当你这样做

int matrix[10][3];

您保留 30 个盒子来保存矩阵值(假设盒子 131 到 160 包括在内)。

现在,假设您想在一个函数中对矩阵中的所有值求和:

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

int但所有函数接收(由标准规定)是指向矩阵第一个元素的指针:指向 3 s数组的指针。所以该函数知道框 131、132 和 133 属于矩阵,但它不知道矩阵的实际长度。

于 2010-10-03T12:14:14.830 回答