在这里把C中有关内存管理的部分稍微总结下,方便以后回头浏览复习。

用于存储数据的内存可用 存储时期作用域链接 来表示。

存储时期:分为 静态的自动的分配的

  • 静态:内存在程序开始执行时被分配,并在程序运行是一致存在。相对应的是静态内存,所需静态内存在编译时就已经决定了,静态数据在程序载入内存的时候也被载入了内存。
  • 自动:变量在内存在程序执行到该变量定义所在的代码块时开始分配,退出代码块时释放。对应的是自动内存,在程序运行时为自动变量分配内存和释放内存,自动变量使用的内存数量会不断变化,可以把自动内存堪称是一个可重写的工作区。
  • 分配:通过malloc(),free()分配和释放。对应的是分配的内存,这种内存数量也会增加或减少,但是这个过程是程序中调用函数控制的,不是自动发生的。

作用域决定哪一部分程序可以访问该变量,或者说该变量对程序的哪部分可见。有文件作用域和代码块作用域。

链接描述了变量对其他文件中的程序是否可见。有外部链接,内部链接,和空连接。

5种存储类:自动寄存器静态空链接,静态内部链接静态、外部链接

这里需要强调的是字符串常量是属于静态存储类。即在一个函数中使用的字符串常量,在整个运行中只存储一次
整个引号中的内容作为指向该字符串存储位置的指针,也就是说字符串常量本身是个指针

大概梳理下通过数组形式初始化字符串的过程:
被引用的字符串存储在可执行文件的数据段部分,当程序被加载到内存的时候,字符串常量也被加载到内存中。被引用的字符串就存储在静态存储区了,然后程序执行的时候为数组分配内存,把字符串内容复制到数组中。

我自己写了个小函数来验证一下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <stdio.h>

void show_s(void);
int main(void)
{
char name[] = "shaozhengjiang";
char * pt;

printf("const address: %p\narray address: %p\n",
&"shaozhengjiang", name); //字符串常量
show_s();

//试图通过指向字符串常量的指针改变字符串的值
pt = "shaozhengjiang";
*(pt + 1) = 'l';
puts("string after changed: ");
puts(pt);
//程序崩溃
return 0;
}

void show_s(void)
{ //查看字符串常量的地址是不是相同
printf("const address in other function: %p\n", &"shaozhengjiang");
}

编译执行结果,

可见,两个函数中的字符串常量的地址是相同的都是<01195858>,也就验证了上面的那个过程,字符串常量属于静态存储类,在程序加载到内存的时候字符串也存入内存,值在程序运行时保持。

Comments