我有 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];
下面声明了一个包含 5 个 int
的数组。
int arr[5];
上面这行代码告诉编译器在从 &arr[0]
开始的相邻内存地址中保留 5 倍于 int
大小的内存。虽然 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 mov al,byte ptr [_array_place+7 (417007h)]
00411383 mov byte ptr [a],al
指针索引:
使用这一行及其 ASM 指令:
char b = p[7];
00412DD7 mov eax,dword ptr [ptr_arg]
00412DDA mov cl,byte ptr [eax+7]
00412DDD mov byte ptr [b],cl
数组可以衰减到指向第一个元素的指针。这种情况经常发生,例如当您将它们作为函数参数传递时。在这种情况下,将它们视为被调用函数内的指针。您最终可以将它们标记为 constant pointers or pointers to constant or constant pointers to constant .
我希望这能澄清。