我已经能够提出以下将二维数组发送到函数的方法:
#include <stdio.h>
# define NUM_TWO_DIM_ROWS 3
# define NUM_TWO_DIM_COLS 5
void iterate_two_dim(int[][NUM_TWO_DIM_COLS]);
void iterate_two_dim1(int (*)[NUM_TWO_DIM_COLS]);
void iterate_two_dim2(int *);
int main() {
int two_dim[][NUM_TWO_DIM_COLS] = { //note the second dimension needs to be specified to resolve expression like two_dim[1]
{1,2,3,4,5}, // second dimension tells how many integers to move the two_dim pointer
{6,7,8,9,10},
{11,12,13,14,15}
};
iterate_two_dim(two_dim);
iterate_two_dim1(two_dim);
iterate_two_dim2(*two_dim);
}
void iterate_two_dim(int two_dim[][NUM_TWO_DIM_COLS]) { //function parameter uses array notation
printf("Two dim array passed using array notation\n" );
for(int row = 0; row < NUM_TWO_DIM_ROWS; row++) {
for(int col = 0; col < NUM_TWO_DIM_COLS; col++) {
printf("two_dim[%d][%d] = %-4d ", row,col, two_dim[row][col] );
}
printf("\n");
}
printf("\n");
}
void iterate_two_dim1(int (*two_dim)[NUM_TWO_DIM_COLS]) { //function parameter uses pointer notation
printf("Two dim array passed using pointer notation\n" );
for(int row = 0; row < NUM_TWO_DIM_ROWS; row++) {
for(int col = 0; col < NUM_TWO_DIM_COLS; col++) {
printf("two_dim[%d][%d] = %-4d ", row,col, two_dim[row][col] );
}
printf("\n");
}
printf("\n");
}
void iterate_two_dim2(int *two_dim) { //function parameter uses pointer notation
printf("Two dim array passed using pointer notation\n" );
char buffer[100];
for(int count = 0; count < NUM_TWO_DIM_ROWS * NUM_TWO_DIM_COLS; count++) {
if(count > 0 && count % NUM_TWO_DIM_COLS == 0 )
printf("\n");
snprintf(buffer, 40, "two_dim[%d] = %2d", count, two_dim[count] );
printf("%-20s", buffer );
}
printf("\n");
}
对于该代码,人们还能想到其他任何方式声明数组two_dim
并如图所示进行初始化吗?
答案 0 :(得分:4)
方法1和2与相同(以及正确的方法)相同。将类型为的数组的参数调整为类型为要指向的指针的参数,即int[][NUM_TWO_DIM_COLS]
在调整后变为int (*two_dim)[NUM_TWO_DIM_COLS]
。
方法3是错误的。您正在访问数组。允许编译器考虑到指针指向NUM_TWO_DIM_COLS
数组的第一个元素的情况,并针对此边界进行边界检查。
C11 Appendix J.2将此列为未定义的行为:
即使显然可以使用给定下标访问对象,数组下标也超出范围(如在声明为int
a[1][7]
的左值表达式a[4][5]
中那样)(6.5.6)。 / p>
答案 1 :(得分:1)
第四种方法是将类型化的指针传递给整个数组,正如我在评论中提到的那样。我没有测试代码,但是您会明白的。请注意,*two_dim_ptr
是整个2D数组,sizeof(*two_dim_ptr)
是 all 元素的数量乘以int
的大小(这是少数情况之一,数组表达式不会衰减到指针)。
**two_dim_ptr
是二维数组的第一个元素,它是包含NUM_TWO_DIM_COLS
个元素的一维数组。因此,sizeof(*two_dim_ptr)/sizeof(**two_dim_ptr)
计算行数。
***two_dim_ptr
是第一行的第一个元素,这里是int
;因此,sizeof(**two_dim_ptr)/sizeof(***two_dim_ptr)
计算一行中的元素数。
使用元素的大小计算索引边界具有维护优势,即如果更改元素类型或常量名称,则无需更改代码。缺点是很难阅读。
void iterate_two_dim_p(int (*two_dim_ptr)[NUM_TWO_DIM_ROWS][NUM_TWO_DIM_COLS]) { //function parameter is pointer to array of specific size
printf("True pointer to two dim array passed\n" );
for(int row = 0; row < sizeof(*two_dim_ptr)/sizeof(**two_dim_ptr); row++) {
for(int col = 0; col < sizeof(**two_dim_ptr)/sizeof(***two_dim_ptr); col++) {
printf("two_dim_ptr[%d][%d] = %-4d ", row,col, two_dim_ptr[row][col] );
}
printf("\n");
}
printf("\n");
}
您可以使用iterate_two_dim_p(&two_dim);
来调用它,即您使用整个数组的地址。(地址运算符的参数位置是数组不衰减的另一种情况结果是二维数组的正确类型化地址,而不仅仅是其第一行的地址。当然,所有地址在数值上都是相同的,因为复合类型的地址是其第一个元素的地址,这是一个适用的规则递归,因此(size_t)&two_dim == (size_t)two_dim && (size_t)two_dim == (size_t)*two_dim
。不同之处在于类型。)