变量在内存中的形式
1.定义
作用域 :变量声明后时,只有在一定区域内才能被访问
存储期:程序中变量的储存终止时间
链接: 链接属性是为了说明在不同文件中出现的相同标识符应该如何处理
- 作用域(分类)
- 块作用域
- 函数作用域
- 文件作用域
ps:作用域只与变量定义的位置有关,在哪里定义,作用域就是哪里!
2.关键字
- auto(void):自动(作用域结束,存储期结束,无链接)
- register:寄存器(不在内存中存储,无法获取地址,但响应快)
- extern:外部变量
- static:
- 静态变量(程序结束,存储期结束)
- 隐藏(表1)
- 默认初始化为0
ps1: 关键字不会影响作用域,只是对存储期和链接的修改
ps2: register---系统根据实际情况,选择是否将变量放入寄存器中
ps3: extern---在文件中使用外部链接变量,要extern声明,否则会被隐藏
ps4: extern---它的作用是表示变量或者函数的定义在别的文件中,而不是创建外部变量
ps5: static---不用担心自己定义的变量,是否会与其它文件中的同名
ps6: 当重名出现时,内层会掩盖外层变量,但不会覆盖(只是另外创建一个新的同名变量)
作用域 | 效果 |
---|---|
文件 | 内部链接,其他文件无法调用 |
主函数 | 内部链接,与系统自动设置相同 |
自定义函数 | 无链接,主要目的是静态变量 |
3.存储类型
存储类别 | 存储期 | 作用域 | 链接 |
---|---|---|---|
自动 | 自动 | 块 | 无 |
寄存器 | 自动 | 块 | 无 |
静态外部链接 | 静态 | 文件 | 外部 |
静态外部链接 | 静态 | 文件 | 内部 |
静态无链接 | 静态 | 块 | 无 |
分配内存
1.malloc()和free()
if(scanf("%d",&max)!=1)
{
puts("Number not correctly entered---bye.");
exit(EXIT_FAILURE);
}
double* ptd;
ptd=(double *)malloc(max*sizeof(double));
long* new;
new=(long *)calloc(max,sizeof(long));
if(ptd == NULL)
{
puts("Memory allocation failed.Goodbye.");
exit(EXIT_FAILURE);//程序意外退出
}
free(ptd);
free(new);
ps1: malloc() free() exit()都在stdlib.h的头文件中
ps2: malloc()返回值是指针,成功为首地址,失败为空指针
ps3: free()能清除malloc()或calloc()分配的内存
ps4: malloc()生成的数组,依然可以进行数组操作
ps5: 使用malloc()后,记得用free()释放动态内存,防止内存泄漏
ps6: 一般exit(EXIT_SUCCESS)表示程序寿终正寝,exit(EXIT_FAILURE)表示死于非命。
ps7: 同一块内存多次使用,对于需要短暂使用内存的部分很使用
ps8: 使用malloc时,有可能无法成功分配内存,一定要判断地址是否为空指针malloc函数的实质体现在,它有一个将可用的内存块连接为一个长长的列表的所谓空闲链表。调用malloc函数时,它沿连接表寻找一个大到足以满足用户请求所需要的内存块。然后,将该内存块一分为二(一块的大小与用户请求的大小相等,另一块的大小就是剩下的字节)。接下来,将分配给用户的那块内存传给用户,并将剩下的那块(如果有的话)返回到连接表上。调用free函数时,它将用户释放的内存块连接到空闲链上。到最后,空闲链会被切成很多的小内存片段,如果这时用户申请一个大的内存片段,那么空闲链上可能没有可以满足用户要求的片段了。于是,malloc函数请求延时,并开始在空闲链上翻箱倒柜地检查各内存片段,对它们进行整理,将相邻的小空闲块合并成较大的内存块。如果无法获得符合要求的内存块,malloc函数会返回NULL指针,因此在调用malloc动态申请内存块时,一定要进行返回值的判断。
2.储存类别与内存分配
存储类别 | 内存分配 |
---|---|
静态储存 | 程序声明建立,程序结束消失 |
自动储存 | 储存在栈中,按顺序加入相反顺序销毁 |
动态分配 | 储存不连续, 使用相对较慢 |
3.程序运行期间的几种内存
1、栈区:由编译器自动分配 存放函数的参数值,局部变量的值等,操作方式类似于数据结构中的栈。
2、堆区:一般由程序员分配释放,若程序员不释放,程序结束时 可能 有系统收回。它与数据结构中的堆是两回事。分配方式类似于链表。
3、全局区(静态区):全局变量和静态变量是存储放在一块的,初始化的全局变量和静态变量在一个区域,未初始化的在相邻的另一个区域。
程序结束后由系统释放。
4、文字常量区:常量字符串就存放在这里。程序结束后有系统自动释放。
5、程序代码区:存放函数体的二进制代码。
4.函数名与内存
- 程序中的函数名、变量名、标号都是一个代号,对应一个地址,就如同指针一样。编译程序在程序中发现你使用函数名时,就会相应替换使用函数名的地方用这个地址*
- 编译后在汇编里面调用的就是纯粹内存地址了之间的调用和我们定义的变量名函数名就没关系了
- 源代码编译后,函数本身成为一个以入口地址开始的连续内容(操作数据段的代码、只有代码,没有数据),函数名将被彻底抹掉。不过有时候你写dll会发现函数名仍然以某种形式保留下来,但是那些名字只是为了提供给程序加载器识别用的。到了执行状态凡是用到的函数,对应的名称都会被替换成代码地址。