Arrays 为什么2D数组的行为类似于指针的一维数组,而不是整数的一维数组?
我一直在研究和测试我在C语言方面的知识(我是一名计算机工程的新生),但遇到了一个我无法解决的问题 在尝试将2D数组传递给函数时,我了解到不能使用动态分配的数组,因为编译器需要知道数组[][列]。但是,我了解到二维数组存储在一维数组中,其中每一新行的元素都紧跟在前一行的元素之后。当我将数组名作为指向数组的指针传递给函数时,情况似乎就是这样,我的代码运行良好。但是,在声明2D数组的函数中,它的行为类似于指针数组Arrays 为什么2D数组的行为类似于指针的一维数组,而不是整数的一维数组?,arrays,c,pointers,multidimensional-array,implicit-conversion,Arrays,C,Pointers,Multidimensional Array,Implicit Conversion,我一直在研究和测试我在C语言方面的知识(我是一名计算机工程的新生),但遇到了一个我无法解决的问题 在尝试将2D数组传递给函数时,我了解到不能使用动态分配的数组,因为编译器需要知道数组[][列]。但是,我了解到二维数组存储在一维数组中,其中每一新行的元素都紧跟在前一行的元素之后。当我将数组名作为指向数组的指针传递给函数时,情况似乎就是这样,我的代码运行良好。但是,在声明2D数组的函数中,它的行为类似于指针数组 #include <stdio.h> void printArray(in
#include <stdio.h>
void printArray(int *A, int* dimA) {
for(int i = 0; i < dimA[0]; ++i) {
for(int j = 0; j < dimA[1]; ++j) {
printf("%3d", A[i*dimA[1] + j]);//This would work if the elements of A[] are the rows of a 2D array mapped into a 1D array
}
printf("\n\n");
}
return;
}
int main(){
int A[2][2] = {{1,2},{3,4}};
int dimA[2] = {2,2};//dimensions of the array
int i, j;
for(i = 0; i < dimA[0]; ++i) {
for(j = 0; j < dimA[1]; ++j) {
printf("%3d", *(A[i] + j)); //This would work if the elements of A[] are pointers
}
printf("\n\n");
}
for(i = 0; i < dimA[0]; ++i) { //Same code as printArray function
for(j = 0; j < dimA[1]; ++j) {
printf("%3d", A[i*dimA[1] + j]);//This would work if the elements of A[] are the rows of a 2D array mapped into a 1D array
}
printf("\n\n");
}
printArray(A, dimA);
return 0;
}
#包括
无效打印数组(int*A,int*dimA){
对于(int i=0;i
当数组被视为指针数组时,以下代码在main()中正确输出该数组,但当数组被视为1D整数数组时则不正确。但是,当我将同一数组作为指针传递给printary函数时,我可以将其视为一维整数数组,并且它可以工作。任何帮助都将不胜感激(我已经知道我可以使用指针数组,但我真的想知道问题出在哪里)。谢谢 根据C标准(6.3.2.1左值、数组和函数指示符) 3除非它是sizeof运算符或一元数的操作数& 运算符,或是用于初始化数组的字符串文本, 类型为“”的数组“”的表达式转换为 类型为“指向类型的指针”且指向初始值的表达式 数组对象的元素,并且不是左值。如果数组 对象具有寄存器存储类,行为未定义 因此,在第一个for循环中
for(i = 0; i < dimA[0]; ++i) {
for(j = 0; j < dimA[1]; ++j) {
printf("%3d", *(A[i] + j)); //This would work if the elements of A[] are pointers
}
printf("\n\n");
}
表达式A[i*dimA[1]+j]
的类型为int*
,并指向数组的i*dimA[1]+j
“行”,即指向数组之外的行。所以这个循环没有意义
函数声明为like
void printArray(int *A, int* dimA);
叫做像
printArray(A, dimA);
类型为int[2]
的第二个参数实际上转换为指向数组第一个元素的类型为int*
的指针
对于第一个参数,它也被转换为指向其第一个元素的指针。数组的元素是什么?此二维数组的元素是int[2]
类型的一维数组。因此,指向此类型对象的指针将具有类型int(*)[2]
指针int*
和int(*)[2]
不兼容,因此编译器应发出诊断消息
函数的正确声明应该如下所示
void printArray(int ( *A )[2], int *dimA);
编译代码时会给出一个警告,提示正在发生的事情:
main.c:27:27: warning: format specifies type 'int' but the argument has type 'int *' [-Wformat]
printf("%3d", A[i*dimA[1] + j]);//This would work if the elements of A[] are the rows of a 2D array mapped into a 1D array
~~~ ^~~~~~~~~~~~~~~~
main.c:32:16: warning: incompatible pointer types passing 'int [2][2]' to parameter of type 'int *' [-Wincompatible-pointer-types]
printArray(A, dimA);
^
main.c:3:22: note: passing argument to parameter 'A' here
void printArray(int *A, int* dimA) {
声明数组时:
int A[2][2] = {{1,2},{3,4}};
如您所述,这将存储为一个连续的内存块。在内存中,这相当于:
int A[4] = {1,2,3,4};
但是,无论何时根据类型查找/取消引用值,编译器都会隐式地为您做一些簿记。对于第二种情况:
int A[4] = {1,2,3,4};
A[0] = *(&A + 0) = 1
A[1] = *(&A + 1) = 2
...
非常简单,索引只是基址的偏移量。然而,对于第一种情况:
y x
int A[2][2] = {{1,2},{3,4}};
y x
A[0][0] = *(&A + 2 * 0 + 0) = *(&A + 0) = 1
A[1][0] = *(&A + 2 * 1 + 0) = *(&A + 2) = 3
...
事情开始看起来有点混乱
首先要注意的是,由于该类型被声明为int[2][2]
,因此必须对其取消引用两次。这就是第一个警告所抱怨的。因为它只被解引用一次,所以您的int**
变成了int*
,这与int
不同
第二件要注意的事情是,由于类型被声明为多维数组,编译器将为您做一些簿记。由于数组在第一维度上被取消引用,因此要跨步到正确位置的第二维度的大小已经被考虑在内,因此您实际上得到的不是col*j+i
,而是col*(col*j+i)+i
,这不是您想要的
要获得所需效果,您可以:
A
转换为int*
。这就是调用printary
函数时发生的情况,也是它工作的原因A[i*dimA[1]+j]
,而是说A[0][i*dimA[1]+j]
。这将正确地取消对int
的引用,并有效地绕过簿记 y x
int A[2][2] = {{1,2},{3,4}};
y x
A[0][0] = *(&A + 2 * 0 + 0) = *(&A + 0) = 1
A[1][0] = *(&A + 2 * 1 + 0) = *(&A + 2) = 3
...
// Dynamically allocating a 2D array of runtime-determined dimensions:
unsigned rows = calculate_number_of_rows();
unsigned columns = calculate_number_of_columns();
int (*matrix)[columns] = malloc(rows * sizeof(*matrix));
void do_something(unsigned rows, unsigned columns, int matrix[rows][columns]);
void do_something(unsigned rows, unsigned columns, int matrix[][columns]);
void do_something(unsigned rows, unsigned columns, int (*matrix)[columns]);