c - 当我定义数组时真正发生了什么

标签 c arrays string pointers memory-address

我编写程序来了解数组和指针之间的区别:

#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终止符),以便在程序启动时进行分配并保持到程序退出。字符串文字不是可修改的,尝试更新一个字符串会导致未定义的行为(这可能意味着您的代码因访问冲突而崩溃,无法按预期工作)。您应该始终将字符串文字视为只读,并且永远不要将其传递给试图对其进行修改的函数(例如strcpystrtok等)。

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


同样,arrptr仅在函数main的生存期内存在。字符串
在整个程序的生存期内,文字"hodaya"存在。

注意:我使用gcc 4.1.2在SLES 10盒上编译了上面的示例(在解决了一些问题之后),是的,即使仅用于初始化.rodata中的字符串文字创建了一个条目。 >。

关于c - 当我定义数组时真正发生了什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25000021/

相关文章:

c - 为什么 sizeof 的赋值会改变从 size_t 赋值给 int 的变量类型?

c - 按位计算负数

python - 三角函数 sin 返回负值

c - C 中的指针和结构数组操作

javascript - 用用户输入的文本替换字符串

java - 我不可能理解所描述的字符串搜索方法。什么是 uFFFF?

c - 警告 :assignment makes integer from pointer without a cast

php - Codeigniter - session 数据未通过数组保存在数据库中

javascript - 如何在 JavaScript 中对包含字母和数字的字符串的数组进行排序

php - CodeIgniter 2.0 - 验证数组