4

So... I have a dynamically allocated array on my main:

int main()
{
    int *array;
    int len;

    array = (int *) malloc(len * sizeof(int));
    ...
    return EXIT_SUCCESS;
}

I also wanna build a function that does something with this dynamically allocated array. So far my function is:

void myFunction(int array[], ...)
{
   array[position] = value;
}

If I declare it as:

void myFunction(int *array, ...);

Will I still be able to do:

array[position] = value;

Or I will have to do:

*array[position] = value;

...?

Also, if I am working with a dynamically allocated matrix, which one is the correct way to declare the function prototype:

void myFunction(int matrix[][], ...);

Or

void myFunction(int **matrix, ...);

...?

4

4 回答 4

6

如果我将其声明为:

void myFunction(int *array, ...);

我还能做到吗:

array[position] = value;

是的 - 这是合法的语法。

另外,如果我正在使用动态分配的矩阵,那么声明函数原型是正确的:

void myFunction(int matrix[][], ...);

或者

void myFunction(int **matrix, ...);

...?

如果您使用多个维度,则必须在函数声明中声明除第一个维度之外的所有维度的大小,如下所示:

void myFunction(int matrix[][100], ...);

此语法不会像您认为的那样做:

void myFunction(int **matrix, ...);
matrix[i][j] = ...

这声明了一个名为的参数matrix,它是一个指向 int 的指针;尝试取消引用 usingmatrix[i][j]可能会导致分段错误。

这是在 C 中处理多维数组的众多困难之一。

这是解决此主题的有用 SO 问题: Define a matrix and pass it to a function in C

于 2013-08-29T23:20:35.820 回答
3

是的,请使用array[position],即使参数类型是int *array. 在这种情况下,您给 ( *array[position]) 的替代方案实际上是无效的,因为[]运算符优先于*运算符,使其等效于*(array[position])which 试图取消引用 的值a[position],而不是它的地址。

对于多维数组,它变得有点复杂,但你可以这样做:

int m = 10, n = 5;

int matrixOnStack[m][n];
matrixOnStack[0][0] = 0;      // OK
matrixOnStack[m-1][n-1] = 0;  // OK
// matrixOnStack[10][5] = 0;  // Not OK. Compiler may not complain
                              // but nearby data structures might.

int (*matrixInHeap)[n] = malloc(sizeof(int[m][n]));
matrixInHeap[0][0] = 0;       // OK
matrixInHeap[m-1][n-1] = 0;   // OK
// matrixInHeap[10][5] = 0;   // Not OK. coloring outside the lines again.

matrixInHeap应该解释声明的方式是指向的“事物”matrixInHeap是一个值数组n int,sosizeof(*matrixInHeap) == n * sizeof(int)或矩阵中整行的大小。matrixInHeap[2][4]之所以有效,是因为matrixInHeap[2]将地址推进matrixInHeap2 * sizeof(*matrixInHeap)这会跳过整整两行n整数,从而产生第三行的地址,然后最终[4]选择第三行中的第五个元素。(请记住,数组索引从 0 开始,而不是 1)

当指向正常的多维 c 数组时,您可以使用相同的类型(假设您已经知道大小):

int (*matrixPointer)[n] = matrixOnStack || matrixInHeap;

现在假设您想要一个将这些可变大小矩阵之一作为参数的函数。当变量较早声明时,该类型具有有关大小的一些信息(堆栈示例中的两个维度,以及堆示例中的最后一个维度n)。因此,函数定义中的参数类型将需要该n值,我们实际上可以这样做,只要我们将其作为单独的参数包含在内,像这样定义函数:

void fillWithZeros(int m, int n, int (*matrix)[n]) {
    for (int i = 0; i < m; ++i)
        for (int j = 0; j < n; ++j)
            matrix[i][j] = 0;
}

如果我们不需要m函数内部的值,我们可以完全忽略它,只要我们保留n

bool isZeroAtLocation(int n, int (*matrix)[n], int i, int j) {
    return matrix[i][j] == 0;
}

然后我们在调用函数时只包含大小:

fillWithZeros(m, n, matrixPointer);
assert(isZeroAtLocation(n, matrixPointer, 0, 0));

可能感觉有点像我们正在让编译器为它工作,特别是在我们根本不在n函数体内使用(或仅作为类似函数的参数)的情况下,但至少它可以工作。

关于可读性的最后一点: usingmalloc(sizeof(int[len]))等效于malloc(len * sizeof(int))(并且任何告诉您否则不理解 c 中的结构填充的人),但是第一种编写方式使读者很明显我们正在谈论数组。malloc(sizeof(int[m][n]))和也是如此malloc(m * n * sizeof(int))

于 2017-04-12T18:43:15.363 回答
1

我还能做到吗:

array[position] = value;

是的,因为索引运算符p[i]与 100% 相同*(ptr + i)。你实际上可以写5[array]而不是array[5]它仍然可以工作。在 C 中,数组实际上只是指针。唯一使数组定义与指针不同的是,如果您采用sizeof“真实”数组标识符,它会为您提供实际分配的存储大小,而采用sizeof指针只会为您提供指针,通常是系统的整数大小(虽然可以不同)。

另外,如果我正在使用动态分配的矩阵,哪一种是声明函数原型的正确方法:(...)

它们都不是,因为它们是指向数组的指针数组,它们可以是非连续的。出于性能原因,您希望矩阵是连续的。所以你只写

void foo(int matrix[])

并在内部计算正确的偏移量,例如

matrix[width*j + i]

请注意,使用括号语法编写此代码看起来很奇怪。另请注意,如果您采用sizeof指针或“未指定长度的数组”函数参数,您将获得指针的大小。

于 2013-08-29T23:23:36.400 回答
1

不,你只会继续使用array[position] = value.

最后,无论您将参数声明为int *something还是,都没有真正的区别int something[]。两者都可以,因为数组定义只是一些隐藏的指针数学。

但是,关于如何理解代码有一个区别:

  • int array[]总是表示一个数组(虽然它可能只有一个元素长)。
  • int *pointer然而可以是指向单个整数或整个整数数组的指针。

就寻址/表示而言:pointer == array == &array[0]

如果您使用多维,情况会有些不同,因为如果您明确定义多维数组,C 会强制您声明最后一个维:

int **myStuff1;    // valid
int *myStuff2[];   // valid
int myStuff3[][];  // invalid
int myStuff4[][5]; // valid
于 2013-08-29T23:24:25.517 回答