a 是&a[0] 的同义词(根据定义),正如 K&R 在“数组和指针”一章中轻轻解释的那样。 &a 没有提到,但可以视为中间步骤。
您必须专注于标识符,这里是a。编译器所需要的只是a 开始的地址及其元素的类型。第二个元素必须在基址加上一个元素大小。
&a 和 &a[0] 是要计算的表达式,而不是要存储的值。 &a[23] 也是计算的,而不是存储的:a + 23 * elemsize。
printf("%p\n", a );
printf("%p\n", a+1 ); // address of next element, not byte
printf("%p\n", &(a[1]) ); // parens not needed
第 2 行和第 3 行在数组开始上方打印 8 个字节(长大小)的地址。
在 0x7ff9c94a10 存在地址本身
也许那个地址确实存在于同一个地方。就像我们都以某种方式做的那样。但它有一个很长的“6”。
要使用地址填充数组,您可以:
void *a[3];
for (int i = 0; i < 3; i++)
a[i] = &a[i];
for (int i = 0; i < 3; i++) {
printf("%p\n", a[i]);
printf("%p\n", &a[i]);
}
打印:
0x7ffe0918cbe0
0x7ffe0918cbe0
0x7ffe0918cbe8
0x7ffe0918cbe8
0x7ffe0918cbf0
0x7ffe0918cbf0
存储一个地址/指针需要 8 个字节。 long 和 void * 在这里大小相同。
printf("%p\n", a+i); 也可以。无需引用取消引用的元素:&a[i]。
一个基本的数组和指针规则是E1[E2] is *(E1 + E2)。 E1 必须指定一个数组,而 E2 和整数,所以
a[i]
*(a + i)
都是一样的。一样
&(a[i])
&a[i]
a + 1
从定义的地址开始的数组的想法很简单。但是说起来……自然语言可以有双重意义:
"Have you seen number 12 today?" (the guest)
"Did you clean number 12?" (not the guest, the room)
困惑
不知何故。但是在void **b = a; 之后,您可以像a 一样使用指针b(只是它有自己的新&b)a = ... 是不可能的(分配给裸数组)。
新示例
您的long 类型非常适合真正存储指向某物的指针,但它使上面的示例变得复杂。这里是一个简单的 int 数组,所以没有人会想要存储地址。它显示了数组和指针共享的内容和不共享的内容:
int main(){
int a[3] = {10,20,30};
int *b;
b = a;
for (int i = 0; i < 3; i++) {
printf("%p\n", &a[i]);
printf("%p\n", &b[i]);
printf("%p %d\n", a+i, a[i]);
printf("%p %d\n", b+i, b[i]);
}
printf("%p\n", a);
printf("%p b = a\n", b);
printf("%p\n", &a);
printf("%p <-- different, &b != &a\n", &b);
return 0;
}
这给出了:
0x7fff72f0ed8c
0x7fff72f0ed8c
0x7fff72f0ed8c 10
0x7fff72f0ed8c 10
0x7fff72f0ed90
0x7fff72f0ed90
0x7fff72f0ed90 20
0x7fff72f0ed90 20
0x7fff72f0ed94
0x7fff72f0ed94
0x7fff72f0ed94 30
0x7fff72f0ed94 30
0x7fff72f0ed8c
0x7fff72f0ed8c b = a (same as top index zero)
0x7fff72f0ed8c
0x7fff72f0ed80 <-- different, &b != &a
差异(12 个字节,“0”代表“c”)并不显着,但这并不重要。 b 除了数组元素还有生命,a 没有。
除此之外,指针b 可以被分配(就像b = a 一样),但数组a 不能。
怎么会?
数组的地址、&array、&array[0]
这其实很不清楚。 array 的地址是 &array(不知何故),但 &array 的地址既不是 &&array(关于标签“数组”的错误)也不是 &(&array)(错误:需要左值) .