C语言学习009-内存知识补充和总结

85 阅读3分钟

1、其实C程序中的内存不是真实的物理内存,是计算机分配给程序的逻辑内存,需要通过转换映射到真正的物理内存上的。
2、一个进程也就是C程序会分配一个虚拟内存用于程序使用,然后映射到物理内存的。
3、C程序内存共分成五大区,每个区的功能不同:

存储的内容
代码区程序二进制代码,也就是要执行的指令等以及字符串常量等常量还有数组名
初始化数据区(data区)存放已经初始化的全局变量和静态变量
未初始化区(bss区)存放未初始化的全局变量和静态变量
堆区存放手动分配内存的变量malloc命令创建的变量,需要手动释放内存free命令
栈区存放函数参数值,内局部变量,静态变量除外,不用手动申请内存,函数结束自动释放

【说明】:有的分法:将代码区中分出一个常量区,将data区和bss区合并成静态区,静态区的声明周期和程序一致,从程序创建到结束一直存在的。
未初始化区中的数据都默认被初始化为0或者NULL。

4、代码区一般是只读的,其中的常量是不可更改的,程序在最初会把所有出现的常量都分配到常量区中,然后分配一个地址,只能使用,不能改里面的内容的。因此char *形式的字符串不能改里面的字符,只能重新赋值,还有数组的名字也是在常量区,所以数组一旦定义就不能重新赋值了。

5、但是char[]数组形式的字符串是可以更改里面字符内容的,因为他是分配在栈上的,静态的分配在静态区,自己手动malloc的分配在堆上,只有最普通的是分配在栈上,随着函数结束就释放了。

6、函数返回局部变量地址:这是不正确的,因为函数结束就是释放了内存,得到的是一个释放的地址,一旦被其他地方用过了,接下来又修改了,可能会导致无法排查的错误。

6、为了返回局部变量的地址:可以将变量定义为静态的,但是静态的就无法释放了,但是可以通过收到那个malloc来创建内存,这样就能手动释放掉了。

7、一个进程中的堆内存是共享的,栈是线程私有的,这一点和java类似,所以堆上分配内存,需要注意多线程中的安全问题。

8、调用函数就往栈里压一个栈帧,调用结束就弹出栈帧,和java类似

9、值传递和地址传递:值传递,参数是基本数据类型,是对传进来数据的拷贝一份,对形参的修改不影响外面实参的数据的;地址传递传过来的是地址的变量,这样就能通过地址间接的修改外面参数的数据了,但是如果对这个指针变量进行重新分配内存,又不会影响原来外面的实参值了。