我已经阅读了一些有关网站中的指针和Internet中的PDF的主题。但是到目前为止,有很多事情我还是不太清楚:
在PDF中写道,可以将具有10行20列的二维数组声明为$ rpm -q --whatprovides /etc/bashrc
setup-2.11.4-1.fc28.noarch
而不是int (*ary)[20]
他们解释:
“
int array[10][20]
被定义为指向一组连续的指针, 一维20个元素的整数数组。”
在互联网上的许多网站上,他们只是说ary
是指向20个整数数组的指针的声明。
答案 0 :(得分:3)
int array[10][20]
是一个包含10个项目的数组,每个项目都是20个整数的数组。或者,如果您愿意:它是10x20 int
的2D数组。
int (*ptr)[20]
是指向20个整数的数组的数组指针。它不会为数组分配任何内存,但是可以指向一个。
如果你写
int array[10][20];
int (*ptr)[20] = array;
然后array
“衰减”为指向第一个元素的指针。 int [10][20]
的第一个元素是int[20]
。并且int (*ptr)[20]
是指向这样一个元素的指针,所以很好。
您可能会因为动态分配2D数组而感到困惑,可以这样做:
int (*ptr)[20] = malloc( sizeof(int[10][20]) );
在这里,ptr
指向int[20]
数组的第一个元素(int[10][20]
)。
答案 1 :(得分:2)
声明
int (*ary)[20];
和
int ary[10][20];
非常 不同。实际上,第一个确实声明了一个指向20个int
元素数组的指针。第二个声明一个由20个int
元素组成的10个数组的数组。
您要记住的是,数组自然会衰减到指向其第一个元素的指针。
对于像这样的简单数组
int simple_array[10];
然后在表达式中使用普通simple_array
与&simple_array[0]
相同,表达式的类型为int *
。
现在是数组数组
int complex_array[10][20];
如果在表达式中使用complex_array
,则它的 still 会导致指向其第一个元素的指针,即&complex_array[0]
。现在的区别是表达式的 type :&complex_array[0]
(或普通等效项complex_array
)是int (*)[20]
。
使用此信息,您可以轻松创建指向complex_array
的指针,并使它指向complex_array
的第一个元素:
int (*complex_array_pointer)[20];
// Make complex_array_pointer point to the first element of complex_array
// i.e. make complex_array_pointer point to complex_array[0]
complex_array_pointer = complex_array;
答案 2 :(得分:1)
主要是要了解C除了一维数组之外没有其他任何东西。是的,C中并不真正存在2D数组(例如矩阵)。
但是,数组包含的元素都具有相同的字节大小(由sizeof
给出)和类型。因此,您可以拥有数字数组,指针数组,struct
-s数组,甚至还有数组数组(例如整数)。
因此,通过滥用,您可以说数组是一个矩阵(因此有人声称C中存在2D数组。我觉得这很夸张)。但是它(例如,声明为int a[10][20];
之类的东西)实际上是一维数组(由20个整数组成)的一维数组(每个元素有10个元素)。在许多情况下,指针数组很有用(例如“字符串”数组)。
C99(或更高版本)中一个有趣的功能是flexible array member s。这样,您就可以巧妙地定义自己的Matrix
abstract data type,用作opaque pointer(有关某些代码,请参见this答案)。
在许多情况下(特别是当您在赋值的右边将数组分配给某个左值(如变量),或将数组作为某个函数的参数传递给数组)时,数组会衰减为指针。但是它们的sizeof
和类型不同。
浏览一些C reference网站(以及更晚的n1570 C标准,例如其§6.5.2.1 Array下标)。阅读How to debug small programs
BTW,在C中很少需要像int a[10][20];
这样的C中所谓的2D数组(除非您专门研究在编译时已知的 fixed 尺寸矩阵上的数值计算;我想游戏开发人员可能经常使用类似typedef double transform3Dmatrix_ty[3][3];
的类型)。在30多年的编程经验中,我几乎从未使用过2D阵列。
我不假装在几个段落中教你C。您会发现很多好书(和一些非常糟糕的书)。
答案 3 :(得分:1)
这些是数组:
int a[10];
int b[10][20];
这些是指针:
int *p1;
int (*p2)[20];
它们是不同的。他们不一样。
但是,即使它们不同,您也可以这样做:
p1 = a;
p2 = b;
现在p1
指向a
,p2
指向b
。
您说的p1 = a
是简写。好像你写过
p1 = &a[0];
严格来说,p1
指向a
的第一个元素。同样,p2 = b
类似于p2 = &b[0]
,并使p2指向b
的第一个元素。但是,由于b
是一个数组数组,所以b
的第一个元素是20个整数数组。
此外,如果您将a
和b
传递给函数,例如:
f(a, b);
该函数的定义应该是什么样?事实证明,有两种方法可以查看它。您可以声明
void f(int a[], int b[20][]) { ... }
这使f
的参数看起来像您认为要传递的参数。但是事实证明实际上是传递了指针,因此f
也可以这样声明:
void f(int *a, int (*b)[20]) { ... }
无论如何,这就是为什么您阅读的页面提示数组int a[10][20]
与指针int (*p2)[20]
之间存在某种等效性的原因。存在“某种等效”,但这并不意味着它们是同一类型。 (完全没有。因此,大多数人宁愿不再在这种情况下使用“对等”一词。)
答案 4 :(得分:-1)
您只需要考虑ary
是指向其第一个元素的指针。请注意,语法ary[index]
与*(ary + index)
是等效的,它将帮助您了解其工作原理。