当我像这样声明一个新数组时:
int foo[5]
foo
是否真的是指向数组的第一个元素的指针?我能这样做吗:
*(foo+2)
如何访问数组的第三个元素?假设我正在创建一个二维数组:
int foo[3][4]
foo
现在是int **
类型吗?
*(foo+2) // 'foo' is implicitly converted into 'int *', pointing to 'foo' first element
foo + 1 //same as above
现在可能会问,'array'类型的属性是什么,为什么我们应该使用它,而不是隐式指向第一个元素的指针。事实是,它们并不多。您可以像这样告诉具有数组类型的对象的大小:
sizeof(foo) //returns the size which array 'foo' occupies
&foo // '&foo' has type of 'int (*)[5]'
您还可以创建带有“数组”引用(或指针)类型参数的函数,以便仅接受具有指定大小的数组(如果它们只是指针并且期望传递的数组衰减为这样,则不可能)。例如:
void func(int (&)[5]);
void func1(int (*arg)[5]); // should be accessed by '*arg', allow the use of null-pointers
void func2(int *); //same as the misleading 'void func2(int [5])' or 'void func2(int [6])' etc.
int foo[5];
int foo1[6];
func(foo); // 'foo' type is ('int [5]') - ok
func1(&foo); // '&foo' type is ('int (*)[5]') - ok
func(foo1); // 'foo1' type is ('int [6]') - not allowed, param type is 'int (&)[5]' !
func1(&foo1); // '&foo1' type is ('int (*)[6]') - not allowed, param type is 'int (*)[5]' !
func2(foo); // 'foo' is implicitly converted to 'int *' - ok
func2(foo1); // 'foo1' is implicitly converted to 'int *' - ok
int (foo[3])[4];
还需要注意的是,'数组'不能被赋值,因此它们不能按值传递或从函数中返回。我的意思是:
int funcReturningArray()[2]; //not allowed
int funcAcceptingArray(int [2]); //just converted into pointer
int funcAcceptingArray(int *); //same as above
尽管由于历史原因(或其他原因?),数组参数在语法上被接受,但它们的真正含义从未被容忍,它们只是被“调整”为指针。
注意:将数组类型隐式转换为其第一个元素的指针有时称为“数组指针衰减”。
//error: wrong type
或 //ok: foo decays into int*
。 - cmaster - reinstate monicadecay
是关键字。应该把它放在开头。 - SwiftMango数组不是指针,但在表达式中它们会被转换为指向其第一个元素的rvalue指针。因此,在这个表达式中
*(foo+2)
int foo[3][4];
在表达式中使用的名称foo被转换为类型为int(*)[4]
的rvalue指针。
rvalue这个词的意思是例如你不能写++foo
也就是编译器为在表达式中使用的数组名称创建一个临时对象,该对象是指向数组第一个元素的指针。
请注意,如果你使用例如操作符sizeof
与数组名称一起使用,则最后一个不会被转换为指针。所以对于你的最后一个数组定义
sizeof( foo )
将等同于
3 * 4 * sizeof( int )
当
sizeof( int ( * )[4] )
将返回指针本身的大小。
最后,如果您将运算符&
应用于数组名称,则会得到指向数组本身的指针。例如
int foo[3][4];
int ( *ptr_to_foo )[3][4] = &foo;
语法
,但实际类型是有区别的。数组不是指针,指针也不是数组。是的,你可以使用数组/指针的语法
来访问各个元素,但它们的类型并不相同。 - PaulMcKenzie