所以…我在我的主要上有一个动态分配的数组:
int main() { int *array; int len; array = (int *) malloc(len * sizeof(int)); ... return EXIT_SUCCESS; }
我还想构建一个函数,用这个动态分配的数组做一些事情。 到目前为止我的function是:
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, ...);
…?
如果我将其声明为:
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问题: 定义矩阵并将其传递给C中的函数
我还能做到:
array[position] = value;
是的,因为索引运算符p[i]
与*(ptr + i)
100%相同。 实际上你可以写5[array]
而不是array[5]
,它仍然可以工作。 在C数组中实际上只是指针。 使数组定义与指针不同的唯一因素是,如果你取一个“true”数组标识符的sizeof
,它会给你实际的存储大小分配,而获取指针的sizeof
只会给你一个大小指针,通常是系统的整数大小(虽然可以不同)。
此外,如果我正在使用动态分配的矩阵,哪一个是声明函数原型的正确方法:( …)
它们都不是因为那些是指向数组的指针数组,它们可以是非连续的。 出于性能原因,您希望矩阵是连续的。 所以你要写
void foo(int matrix[])
并在内部计算正确的偏移量,如
matrix[width*j + i]
请注意,使用括号语法编写此内容看起来很奇怪。 另请注意,如果您获取指针的sizeof
或“未指定长度数组”函数参数,您将获得指针的大小。
不,你只是继续使用array[position] = value
。
最后,无论你是将一个参数声明为int *something
还是int something[]
,都没有什么区别。 两者都有效,因为数组定义只是一些隐藏的指针数学。
但是,关于如何理解代码存在一个区别:
就寻址/表示而言: pointer == array == &array[0]
如果您正在使用多个维度,那么事情就会有所不同,因为如果您明确定义多维数组,C会强制您声明最后一个维度:
int **myStuff1; // valid int *myStuff2[]; // valid int myStuff3[][]; // invalid int myStuff4[][5]; // valid
是的,请使用array[position]
,即使参数类型是int *array
。 您给出的替代方法( *array[position]
)在这种情况下实际上是无效的,因为[]
运算符优先于*
运算符,使其等效于*(array[position])
,它试图取消引用a的值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
指向的’thing’是一个n
int
值的数组,所以sizeof(*matrixInHeap) == n * sizeof(int)
,或者整个行的大小矩阵。 matrixInHeap[2][4]
工作原理是因为matrixInHeap[2]
将地址matrixInHeap
推进2 * sizeof(*matrixInHeap)
,跳过两行n
整数,得到第3行的地址,然后是最后的[4]
从第三行中选择第五个元素。 (记住数组索引从0开始而不是1)
指向普通的多维carrays时,可以使用相同的类型(假设您已经知道了大小):
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))
。
以上就是c/c++开发分享将动态分配的数组作为参数传递给C语言相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/c-cdevelopment/560030.html