C++ 指向数组第一个元素的指针的地址?
我对指向数组开头的指针在内存中的位置有点困惑。据我所知,数组和指针可以使用相同的函数,如*、&和[]。因此,如果我创建一个字符数组,我理解为:buffer==&buffer[0] 所以不带括号的arrayname就像一个指针,它包含数组第一个条目的地址,对吗 但是,当我试图找出指针的地址(存储&buffer[0]的地址)时,它会给我与指针(&arrayname[0])中存储的值相同的值。这怎么可能?虚拟ram中的同一地址如何包含地址和缓冲区[0]的值(其在下面的代码中等于'H')C++ 指向数组第一个元素的指针的地址?,c++,c,arrays,pointers,C++,C,Arrays,Pointers,我对指向数组开头的指针在内存中的位置有点困惑。据我所知,数组和指针可以使用相同的函数,如*、&和[]。因此,如果我创建一个字符数组,我理解为:buffer==&buffer[0] 所以不带括号的arrayname就像一个指针,它包含数组第一个条目的地址,对吗 但是,当我试图找出指针的地址(存储&buffer[0]的地址)时,它会给我与指针(&arrayname[0])中存储的值相同的值。这怎么可能?虚拟ram中的同一地址如何包含地址和缓冲区[0]的值(其在下面的代码中等于'H') #包括 #包括
#包括
#包括
void main(){
字符缓冲区[]=“你好”;
printf(“地址缓冲区:%d\n”,&buffer);
printf(“值缓冲区:%d\n”,缓冲区);
printf(“地址缓冲区[0]:%d\n”,&buffer[0]);
printf(“值缓冲区[0]:%c\n”,缓冲区[0]);
printf(“地址缓冲区[1]:%d\n”,&buffer[1]);
系统(“暂停”);
}
所以基本上我被第一个输出搞糊涂了。它不应该与第二个不同吗?非常感谢你的解释
这是错误的:
printf("Address buffer: %d\n", &buffer);
printf("Value buffer: %d\n", buffer);
假设数组为指针的正确代码如下:
printf("Address buffer: %p\n", (void*) buffer);
printf("Value buffer: %d\n", *buffer);
您可以将array[x]
转换为*(array+x)
,这意味着:
读取数组+其元素大小的x所指向的内存区域
除非它是
sizeof
或一元&
运算符的操作数,或者是用于初始化声明中另一个数组的字符串文字,否则“T的N元素数组”类型的表达式将转换(“衰减”)为“指向T
的指针”类型的表达式,表达式的值将是数组第一个元素的地址
假设以下代码:
char buffer[] = "Hello";
...
printf( "%s\n", buffer );
在对printf
的调用中,表达式buffer
的类型为“char的6元素数组”;由于它不是sizeof
或一元&
运算符的操作数,也不是用于初始化声明中的另一个数组,因此该表达式将转换(“衰减”)为“指向char
”类型的表达式(char*
),表达式的值是数组中第一个元素的地址
现在,将printf
调用更改为
printf( "%p", (void *) &buffer );
这次,buffer
是一元&
运算符的操作数;不会自动转换为类型“指向char
”的指针。相反,表达式&buffer
的类型是“指向char
的6元素数组的指针”,或char(*)[6]
1(括号很重要)
两个表达式产生相同的值——数组的地址与数组第一个元素的地址相同——但两个表达式的类型不同。这很重要<代码>字符*和字符(*)[6]
不可互换
那么,为什么这种时髦的转换魔法一开始就存在呢
当丹尼斯·里奇最初设计C时,他的设计是基于一种早期的语言B(go figure)。在B中分配数组时,如下所示:
auto arr[N];
编译器将为数组内容留出N个元素,以及存储数组第一个元素偏移量的附加单元格(基本上是指针值,但没有任何类型语义;B是“无类型”语言)。此附加单元格将绑定到变量arr
,提供如下内容:
+---+
arr: | | --+
+---+ |
... |
+---+ |
arr[0]: | | <-+
+---+
arr[1]: | |
+---+
arr[2]: | |
+---+
... ...
+---+
arr[N-1]: | |
+---+
他想要一个2字节的整数,后跟一个14字节的数组;没有一个好地方可以存放指向数组第一个元素的指针
所以他把它扔掉了;他没有为指向数组第一个元素的指针留出存储空间,而是设计了该语言,以便从数组表达式本身计算数组的位置。因此,这篇文章开头的规则是这样的
1.
%p
转换说明符需要一个void*
表达式作为其相应的参数,因此需要强制转换。请阅读一本好的C(或C++)编程书籍。他们解释了所有的细节。(基本上,数组可以衰减为指针)。并使用%p
到printf
指针。@BasileStarynkevitch这不是他的要求。要打印出地址,请使用%p
转换说明符。此处已回答的可能重复项:不,您应该使用%p
到printf
指针(然后最好显式地将它们强制转换为void*
)抱歉,也许我的输出有点误导:通过“值缓冲区”:我的意思是值缓冲区本身等于,所以在本例中是地址,而不是地址指向的值。哇,你的回答给我留下了深刻的印象,解释得很好,非常感谢你花时间回答。关于整个“从数组表达式计算”事情,你能给我一个关于这一点的链接或名称吗?@user2352375:好吧,你可以从(在线草案)开始;第6.3.2.1节是最相关的。里奇也描述了他是如何开发C。
+---+
arr: | | --+
+---+ |
... |
+---+ |
arr[0]: | | <-+
+---+
arr[1]: | |
+---+
arr[2]: | |
+---+
... ...
+---+
arr[N-1]: | |
+---+
struct {
int inode;
char name[14];
};