int main(){
long a[]={6,9,10};
printf("%p\n",a);
printf("%p\n",&a);
printf("%p\n",&a[0]);
return 0;
}结果是:
0x7ff9c94a10
0x7ff9c94a10
0x7ff9c94a10这个结果真的让我很困惑!为什么它在相同的内存位置存储不同的值,在0x7ff9c94a10同时存在地址本身和值6
发布于 2021-05-04 21:07:02
一张图片应该会有帮助-我们假设64位long
+––––––+
0x7ff9c94a10 | 0x06 | a[0]
+––––––+
0x7ff9c94a18 | 0x09 | a[1]
+–––—––+
0x7ff9c94a20 | 0x0a | a[2]
+–––––—+没有独立于数组元素本身的对象a,因此数组(&a,类型long (*)[3])的地址与其第一个元素(&a[0],类型long *)的地址相同。
除非它是sizeof或一元&运算符的操作数,或者是用于在声明中初始化字符数组的字符串文字,否则“T的N元素数组”类型的表达式将被转换为“指向T的指针”类型的表达式,并且表达式的值是数组的第一个元素的地址,因此表达式a实际上与&a[0]相同,并且也具有类型long *。
发布于 2021-05-04 17:41:26
正如K&R在“数组和指针”一章中所解释的那样,a (根据定义)是&a[0]的同义词。没有提到&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和integer,因此
a[i]
*(a + i)都是一样的。按原样
&(a[i])
&a[i]
a + 1数组从定义的地址开始的想法很简单。但是谈论it...natural语言可以有双重含义:
"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 (不知何故),但&array的地址既不是&&array (关于标签‘&array’的错误)也不是&(&array) (错误:需要左值)。
发布于 2021-05-07 00:04:55
井,
array根据定义,是第一个元素的地址,这等同于:
&array[0]这就解释了为什么两者都有相同的地址。
第二个表达式是数组的地址。通常,(我现在不记得这是不是由标准强制执行的)数组是通过一个接一个的元素存储的,从第一个元素开始……因此,数组地址与第一个元素的地址相同是正常的。但是,如果您检查指向对象的类型,您将看到这些表达式之间的差异:
*array是数组的元素的类型,而
*&array是整个数组类型。
所以,让我们假设你有
char array[10];然后
array的类型
char *和
*array类型为char,而
&array的类型为10个字符的数组,或者
char [10]如何验证这一点?只需运行以下程序:
#include <stdio.h>
/* print the expression and it's size */
#define P(T) printf("sizeof("#T") == %zu\n", sizeof(T))
int main()
{
char array[10];
P( array );
P( *array );
P( &array );
P( *&array );
P( array[0] );
P( &array[0] );
P( *&array[0] );
}当(在我的系统上)运行时,它会产生:
$ a.out
sizeof(array) == 10 <-- the size of the array
sizeof(*array) == 1 <-- the size of the pointed to first element (as by def)
sizeof(&array) == 8 <-- size of a pointer to the array.
sizeof(*&array) == 10 <-- size of the pointed to object (the array)
sizeof(array[0]) == 1 <-- size of the first element.
sizeof(&array[0]) == 8 <-- size of a pointer to the first element (as above)
sizeof(*&array[0]) == 1 <-- size of the pointed to first element.
$ _(右边的文字是对数字的解释)
关于&&的错误的原因(这属于给出的答案之一,由于某种原因,已经将&链接到它的两个应用程序中,并得到了关于标签运算符的错误)是,对于语言的GCC扩展,GCC有一个一元运算符&&。在C中没有&&一元运算符,如果你继续使用-pedantic,你会得到一个错误,当你尝试使用不带左操作数的逻辑与运算符(&&)时,会出现语法错误。无论如何,如果您尝试像下面这样分隔操作数
& & array然后你会得到另一个错误,因为子表达式&array没有表示左值(在内存中没有表示),因此不能应用&左一元运算符(你不能获得值的地址)。
你的最后一段很有趣:你说
这个结果真的让我很困惑!为什么它在相同的内存位置存储不同的值,在0x7ff9c94a10同时存在地址本身和值6
它们并不是不同的价值观。这里的问题是,三个不同的表达式中的两个表示不同的东西,但在相同的位置,因为数组在内存中从与其第一个元素相同的点开始。
你在家里的时候,你和你的房子有相同的邮寄地址,但是你和你的房子是不一样的,对不对?这就是这里正在发生的事情:&array (是您的房子的地址,数组)和&array[0] (是您的地址,它与房子的邮寄地址相同,因为您在房子里)。问题是你有三个表达式,你不知道表达式array的意思是,通过它的定义,字面上是指向第一个元素的指针,这使得它等同于&array[0] (类似于缩写)。因此,我们结束了三个具有相同值的表达式,其中两个是相同的东西(确切地说),另一个表示不同的东西。可能在你读完这一段之后,你需要再读一遍上面这个简单程序的输出,然后你就会发现不同之处在哪里(显然,你的房子比你大)
https://stackoverflow.com/questions/67379858
复制相似问题