【问题标题】:Passing dynamically allocated array as a parameter in C在C中将动态分配的数组作为参数传递
【发布时间】:2025-12-24 09:05:11
【问题描述】:

所以...我的主服务器上有一个动态分配的数组:

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

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

我还想构建一个函数来处理这个动态分配的数组。 到目前为止,我的功能是:

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

如果我将其声明为:

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

我还能做到吗:

array[position] = value;

否则我将不得不这样做:

*array[position] = value;

...?

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

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

或者

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

...?

【问题讨论】:

    标签: c arrays matrix


    【解决方案1】:

    如果我将其声明为:

    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 的指针;尝试使用 matrix[i][j] 取消引用可能会导致分段错误。

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

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

    【讨论】:

    • 好的,但是也可以声明为void myFunction(int **matrix, ...) 并使用类似matrix[i][j] = value 的东西吗?
    • @ThiG。我更新了我的答案以解决您的问题。我希望这会有所帮助!
    【解决方案2】:

    是的,请使用array[position],即使参数类型是int *array。在这种情况下,您提供的替代方案 (*array[position]) 实际上是无效的,因为 [] 运算符优先于 * 运算符,使其等效于试图取消引用 a[position] 的值的 *(array[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 值的数组,因此sizeof(*matrixInHeap) == n * sizeof(int) 或整行的大小矩阵。 matrixInHeap[2][4] 起作用是因为matrixInHeap[2] 将地址matrixInHeap 推进2 * 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(或仅作为类似函数的参数)的情况下,但在至少它有效。

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

    【讨论】:

      【解决方案3】:

      我还能做到吗:

      array[position] = value;
      

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

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

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

      void foo(int matrix[])
      

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

      matrix[width*j + i]
      

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

      【讨论】:

        【解决方案4】:

        不,你只需要继续使用array[position] = value

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

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

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

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

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

        int **myStuff1;    // valid
        int *myStuff2[];   // valid
        int myStuff3[][];  // invalid
        int myStuff4[][5]; // valid
        

        【讨论】: