我编写程序来理解数组和指针之间的区别:
#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
。
但是当我定义数组时会发生什么?
答案 0 :(得分:3)
首先,除非您的编译器文档显式将void main()
列为main
函数的有效签名,否则请改用int main(void)
。在大多数情况下,main
假定将值返回给运行时环境(即使它只是EXIT_SUCCESS)。
让我们来谈谈宣言
char arr [] ="hodaya";
"hodaya"
是一个字符串文字;它存储为char
的7个元素数组(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
”将被转换(“衰减”)为“指向T
的指针”类型的表达式,表达式的值将是第一个元素的地址在数组中。结果不是左值;也就是说,它不能成为作业的目标。
这很重要,也是很多混淆的来源。 arr
不是指针;它不包含地址。当编译器在大多数上下文中看到arr
时,它将用它的第一个元素的地址替换,并且结果表达式的类型将是char *
。但是,如果arr
是一元&
运算符的操作数,则替换不会发生。表达式的值是相同的(数组的地址与数组的第一个元素的地址相同),但类型是不同的;而不是char *
,&arr
的类型是char (*)[7]
(指向char
的7元素数组的指针)。
因此,在宣言中
char *ptr = arr;
arr
不是一元&
运算符(或任何其他运算符)的操作数,因此应用转换规则,以及{{{}的第一个元素的地址 1}}写入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
存在于整个程序的生命周期中。
注意:我使用gcc 4.1.2在SLES 10盒子上编译了上面的例子(在解决了几个问题之后),是的,它为"hodaya"
中的字符串文字创建了一个条目,甚至虽然它只用于初始化.rodata
。
答案 1 :(得分:-3)
arr
保存数组中第一个元素的地址(&arr[0]
)。
在这里,您始终在阅读元素的地址而不是值。
arr[0] = 'a', arr[1] = 'b', arr[2] = 'c', arr[3] = 0;
char *ptr = arr;
*ptr++ = 'a', *ptr++ = 'b', *ptr++ = 'c', *ptr = 0;