我来自Java背景,在C语言中我对C数组语法有点困惑。
当我在 C 中初始化数组时,我这样做:
int arr[5];
据我正确理解,这实际上给出了一个指向 arr 的指针,该指针指向堆栈上数组的第一个元素。
但是我不明白为什么数组初始化看起来不像这样,因为我们收到一个指针:
int* arr[5];
这给了我一些我不明白的东西。也许是 5 个指针的数组?
另一方面,这再次完全有效:
int arr[5];
int* p = arr;
那么为什么要这样做呢?初始化语法不应该使用 int* 而不是 int,因为我们实际上会收到一个指针吗?
在 C 语法中,此行声明了一个包含 5 个指向int
的指针的数组。
int* arr[5];
在 5int
s 的数组下方声明。
int arr[5];
上面的行告诉编译器从&arr[0]
开始,在内存的相邻地址中保留int
5 倍于内存大小的 5 倍。虽然arr
不是指针,但它本身,如果用作名称,arr
,衰减到指向第一个插槽的指针(所以arr
等效于&a[0]
(。
int* p = arr;
p
是指向int
的普通指针,分配给一个有效的内存地址,与arr
(或&arr[0]
(相同
数组和指针不同。第一个区别是"arr"是一个常量,不能重新分配给其他地址。
例如,以下内容无效
arr++;
虽然以下内容有效
p++;
此外,指针需要额外的取消引用底层 ASM 操作,而数组不需要
char arr[7];
char *p = arr;
数组索引
比较此行及其 ASM 指令:
char a = arr[7];
0041137E 移动,字节 ptr [_array_place+7 (417007h(]
00411383 MOV字节PTR [a],al
指针索引:
使用此行及其 ASM 说明:
char b = p[7];
00412DD7 移动 eax,dword PTR [ptr_arg]
00412DDA 移动 cl,字节 ptr [EAX+7]
00412DDD 移动字节 ptr [b],cl
数组可以衰减到指向第一个元素的指针。这种情况经常发生,例如,当您将它们作为函数参数传递时。在这种情况下,请将它们视为被调用函数内的指针。您最终可以将它们标记为常量指针或指向常量的指针或指向常量的常量指针。
我希望这能澄清。