我编写程序来了解数组和指针之间的区别:
#include <stdio.h>
void main()
{
char arr [] ="hodaya",*ptr=arr;
printf("arr=%p\n",arr);
printf("&arr=%p\n",&arr);
printf("ptr=%p\n",ptr);
printf("&ptr=%p\n",&ptr);
}
结果:
arr=0xbfd26265
&arr=0xbfd26265
ptr=0xbfd26265
&ptr=0xbfd26260
所以我读了下面的答案:
how-come-an-arrays-address-is-equal-to-its-value-in-c
它回答了我的大部分问题,我只剩下一个问题!
我了解,当我定义指针时,我定义了(在特定地址中)保留地址的空间,因此我可以采用这样的指针地址:
&ptr
。但是,当我定义数组时会发生什么?
最佳答案
首先,除非您的编译器文档明确列出void main()
作为main
函数的有效签名,否则请使用int main(void)
。在大多数情况下,main
应该将值返回到运行时环境(即使只是EXIT_SUCCESS)。
所以我们来谈谈宣言
char arr [] ="hodaya";
"hodaya"
是字符串文字;它存储为7个元素的char
数组(6个字符加0终止符),以便在程序启动时进行分配并保持到程序退出。字符串文字不是可修改的,尝试更新一个字符串会导致未定义的行为(这可能意味着您的代码因访问冲突而崩溃,无法按预期工作)。您应该始终将字符串文字视为只读,并且永远不要将其传递给试图对其进行修改的函数(例如strcpy
,strtok
等)。arr
被声明为char
的数组,并将使用字符串文字"hodaya"
的内容进行初始化。数组的大小取自初始化器(7)的大小。该声明大致等于:char arr[7];
strcpy( arr, "hodaya" );
也可以写成
char arr[] = {'h', 'o', 'd', 'a', 'y', 'a', 0 };
结果相同(用字符串
arr
初始化的"hodaya"
),语法略有不同。在这种情况下,不会创建字符串文字。由于您在
arr
本地声明了main
(据说具有自动存储持续时间,这意味着该函数退出时将释放内存),因此可以通过arr[0]
修改arr[6]
的内容。现在让我们讨论
ptr
的声明。除非它是
sizeof
或一元&
运算符的操作数,或者是用于在声明中初始化另一个数组的字符串文字,否则将转换类型为“ T
的N个元素的数组”的表达式(“ decay”)到类型为“ T
的指针”的表达式,该表达式的值将是数组中第一个元素的地址。结果不是左值;也就是说,它不能成为任务的目标。这很重要,并且引起很多混乱。
arr
不是指针;它不包含地址。在大多数情况下,当编译器看到arr
时,它将用其第一个元素的地址替换它,并且所得表达式的类型将为char *
。但是,如果arr
是一元&
运算符的操作数,则不会发生替换。表达式的值是相同的(数组的地址与数组的第一个元素的地址相同),但是类型不同。 char *
的类型不是&arr
,而是char (*)[7]
(指向char
的7元素数组的指针)。因此,在声明中
char *ptr = arr;
arr
不是一元&
运算符(或任何其他运算符)的操作数,因此适用转换规则,并且arr
的第一个元素的地址被写入ptr
。到您完成时,您的内存看起来类似于以下内容(地址不代表任何实际的体系结构):
Item Address 0x00 0x01 0x02 0x03
---- ------- ---- ---- ---- ----
"hodaya" 0x40040 'h' 'o' 'd' 'a'
0x40044 'y' 'a' 0 ??
...
arr 0x7fffb220 'h' 'o' 'd' 'a'
0x7fffb224 'y' 'a' 0 ??
ptr 0x7fffb228 0x7f 0xff 0xb2 0x28
同样,
arr
和ptr
仅在函数main
的生存期内存在。字符串在整个程序的生存期内,文字
"hodaya"
存在。注意:我使用gcc 4.1.2在SLES 10盒上编译了上面的示例(在解决了一些问题之后),是的,即使仅用于初始化
关于c - 当我定义数组时真正发生了什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25000021/