0x01 存储类别

1、作用域

一个C变量的作用域可以是块作用域、函数作用域、函数原型作用域或文件作用域。
1.1 块作用域
块是用一对花括号括起来的代码区域。比如函数体就是一个块。定义在块中的变量具有块作用域,块作用域变量的可见范围是从定义处到包含该定义的块的末尾

1.2 函数作用域
仅用于goto语句的标签。一个标签首次出现在函数的内层块中,它的作用域也延伸至整个函数

1.3 函数原型作用域
用于函数原型中的形参名,作用范围是从形参定义处到原型声明结束。这意味着,编译器在处理函数原型中的形参时只关心它的类型,而形参名通常无关紧要。

1.4文件作用域
变量的定义在函数外面,具有文件作用域,从它的定义处到该定义所在文件的末尾均可见。

2、链接

C变量有3种链接属性:外部链接、内部链接或无链接。具有块作用域、函数作用域或函数原型作用域的变量都是无链接变量。这意味着这些变量属于定义他们的块、函数或原型私有。具有文件作用域的变量可以是外部链接或内部链接。外部链接变量可以在多文件程序中使用,内部链接变量只能在一个文件中使用。当一个文件作用域变量用static修饰时就是内部链接

3、存储期

C有4种存储期:静态存储期、线程存储期、自动存储期、动态分配存储期

  • 静态存储期:在程序的执行期间一直存在,文件作用域具有静态存储期
  • 线程存储期:用于并发程序设计,程序执行可被分为多个线程。从被声明到线程结束一直存在
  • 自动存储期:块作用域的变量通常都具有自动存储期,当程序进入定义这些变量的块时,为这些变量分配内存,当退出这个块时,释放刚才为变量分配的内存
4、存储类别说明符
  • auto:表名变量是自动存储期,只能用于块作用域的变量声明中。由于在块中声明的变量本身就具有自动存储期,所以使用auto主要是为了明确表达要使用外部变量同名的局部变量的意图。
  • register 说明符也只用于块作用域的变量,它把变量归为寄存器存储类别,请求最快速度访问该变量。同时,还保护了该变量的地址不被获取。
  • static 说明符创建的对象具有静态存储期,载入程序时创建对象,当程序结束时对象消失。如果static 用于文件作用域声明,作用域受限于该文件。如果 static 用于块作用域声明,作用域则受限于该块。
  • extern 说明符表明声明的变量定义在别处。如果包含 extern 的声明具有文件作用域,则引用的变量必须具有外部链接。如果包含 extern 的声明具有块作用域,则引用的变量可能具有外部链接或内部链接,这接取决于该变量的定义式声明。
5、小结

0x02 存储类别和函数

函数也有存储类别,可以是外部函数(默认)或静态函数。外部函数可以被其他文件的函数访问,但是静态函数只能用于其定义所在的文件。

double gamma(double);   /* 该函数默认为外部函数 */
static double beta(int, int);
extern double delta(double, int);

在同一个程序中,其他文件中的函数可以调用gamma()和delta(),但是不能调用beta(),因为以static存储类别说明符创建的函数属于特定模块私有。这样做避免了名称冲突的问题,由于beta()受限于它所在的文件,所以在其他文件中可以使用与之同名的函数。
通常的做法是:用 extern 关键字声明定义在其他文件中的函数。这样做是为了表明当前文件中使用的函数被定义在别处。除非使用static关键字,否则一般函数声明都默认为extern。

在rand0.c文件里:

static unsigned long int next=1;
unsigned int rand0(void)
{next=next*1103515245+12345;return (unsigned int) (next / 65536 )%32768;
}

在r_drive0.c文件里

#include "stdio.h"extern unsigned int rand0(void);int main(void)
{int count;for(count = 0;count<5;count++)printf("%d\n",rand0());return 0;
}

next是静态内部链接,存储期在程序的执行期间一直存在,作用域是rand0.c文件,其他就不可以访问了。
unsigned int rand0(void)是外部函数,其他文件可以调用,用 extern 关键字声明定义rand0.c文件里

0x03 分配内存 malloc()和free()

  • malloc():接收一个参数,是所需内存的字节数,返回动态分配内存块的首字节地址。如果 malloc()分配内存失败,将返回空指针。malloc会找到合适的空闲内存块,这样的内存是匿名的,malloc()函数可用于返回指向数组的指针、指向结构的指针等,所以通常该函数的返回值会被强制转换为匹配的类型
  • free()函数的参数是之前malloc()返回的地址,该函数释放之前malloc()分配的内存,一些操作系统在程序结束时会自动释放动态分配的内存,但是有些系统不会。为保险起见,请使用free(),不要依赖操作系统来清理。
  • malloc()和free()的原型都在stdlib.h头文件中。
  • 因为char表示1字节,malloc()的返回类型通常被定义为指向char的指针。然而,从ANSI C标准开始,C使用一个新的类型:指向void的指针,把指向 void的指针赋给任意类型的指针完全不用考虑类型匹配的问题
#include "stdlib.h"
#include "stdio.h"int main(void)
{double *ptd;int max=5;int number;int i;ptd=(double *)malloc(max*sizeof(double));for(i=0;i<max;i++){ptd[i]=i;printf("%f\n",ptd[i]);}free(ptd);return 0;}

上面的程序是动态分配数组

反汇编:

6:        double *ptd;
7:        int max=5;
00401028 C7 45 F8 05 00 00 00 mov         dword ptr [ebp-8],5
8:        int number;
9:        int i;
10:
11:       ptd=(double *)malloc(max*sizeof(double));
0040102F 8B 45 F8             mov         eax,dword ptr [ebp-8]
00401032 C1 E0 03             shl         eax,3
00401035 50                   push        eax
00401036 E8 95 00 00 00       call        malloc (004010d0)
0040103B 83 C4 04             add         esp,4
0040103E 89 45 FC             mov         dword ptr [ebp-4],eax
12:
13:           for(i=0;i<max;i++)
00401041 C7 45 F0 00 00 00 00 mov         dword ptr [ebp-10h],0
00401048 EB 09                jmp         main+43h (00401053)
0040104A 8B 4D F0             mov         ecx,dword ptr [ebp-10h]
0040104D 83 C1 01             add         ecx,1
00401050 89 4D F0             mov         dword ptr [ebp-10h],ecx
00401053 8B 55 F0             mov         edx,dword ptr [ebp-10h]
00401056 3B 55 F8             cmp         edx,dword ptr [ebp-8]
00401059 7D 2A                jge         main+75h (00401085)
14:           {15:               ptd[i]=i;
0040105B DB 45 F0             fild        dword ptr [ebp-10h]
0040105E 8B 45 F0             mov         eax,dword ptr [ebp-10h]
00401061 8B 4D FC             mov         ecx,dword ptr [ebp-4]
00401064 DD 1C C1             fstp        qword ptr [ecx+eax*8]
16:               printf("%f\n",ptd[i]);
00401067 8B 55 F0             mov         edx,dword ptr [ebp-10h]
0040106A 8B 45 FC             mov         eax,dword ptr [ebp-4]
0040106D 8B 4C D0 04          mov         ecx,dword ptr [eax+edx*8+4]
00401071 51                   push        ecx
00401072 8B 14 D0             mov         edx,dword ptr [eax+edx*8]
00401075 52                   push        edx
00401076 68 1C 60 42 00       push        offset string "%f" (0042601c)
0040107B E8 D0 1F 00 00       call        printf (00403050)
00401080 83 C4 0C             add         esp,0Ch
17:           }
00401083 EB C5                jmp         main+3Ah (0040104a)
18:           free(ptd);
00401085 8B 45 FC             mov         eax,dword ptr [ebp-4]
00401088 50                   push        eax
00401089 E8 C2 0A 00 00       call        free (00401b50)
0040108E 83 C4 04             add         esp,4
19:
20:

ptd=(double )malloc(maxsizeof(double));的反汇编是:

0040102F 8B 45 F8             mov         eax,dword ptr [ebp-8]
00401032 C1 E0 03             shl         eax,3
00401035 50                   push        eax
00401036 E8 95 00 00 00       call        malloc (004010d0)
0040103B 83 C4 04             add         esp,4
0040103E 89 45 FC             mov         dword ptr [ebp-4],eax

先将max的值传给eax,左移eax三位,相当于eax乘以8,就是40,刚好是传给malloc的参数值,然后压栈,调用malloc函数,再把eax存入dword ptr [ebp-4]中。
free(ptd);反汇编:

00401085 8B 45 FC             mov         eax,dword ptr [ebp-4]
00401088 50                   push        eax
00401089 E8 C2 0A 00 00       call        free (00401b50)
0040108E 83 C4 04             add         esp,4

先把dword ptr [ebp-4]的值传给eax,就是40,是malloc分配内存的大小,eax入栈,调用free函数,释放这段内存

C和汇编----存储类别、链接和内存管理相关推荐

  1. C语言复习-存储类别,链接和内存管理

    存储类 从硬件方面来看,被存储的每个值都占一定的物理内存.C语言把这一块内存称为对象.对象可以存储一个或多个值.一个对象可能并未存储到实际的值,但是它在存储适当的值时一定具有相应的大小. 从软件方面来 ...

  2. 第九章 存储类别、链接和内存管理

    文章目录 存储类别 作用域 翻译单元和文件 链接 存储期 5种存储类别 自动变量 寄存器变量 块作用域的静态变量 外部链接的静态变量 内部链接的静态变量 多文件 存储类别说明符 存储类别和函数 随机函 ...

  3. C语言基础笔记之12:存储类别、链接和内存管理

    Tips1: 关键字:auto.extern.static.register.const.volatile.restricted. _Thread_local._Atomic 函数:rand().sr ...

  4. 《C Primer Plus》读书笔记——存储类、链接和内存管理

    背景 距离上次写读书笔记的日子已有半个月了.这段时间一直在做摄像头直立平衡车,也把<C Primer Plus>的中级部分扫了一遍.现在做赛道算法识别遇到瓶颈了,就想把读书笔记补回来.原计 ...

  5. 第十二章 存储类别、链接和内存管理

    程序清单12.1,hiding.c: // hiding.c -- 块中的变量 #include <stdio.h>int main(void) {int x = 30; // 原始的 x ...

  6. C Primer Plus(6) 中文版 第12章 存储类别、链接和内存管理 12.3 掷骰子

    12.3 掷骰子 最普遍的是使用两个6面骰子.在一些冒险游戏中,会使用5种骰子:4面.6面.8面.12面和20面.聪明的古希腊人证明了只有5种正多面体,它们的所有面都具有相同的形状和大小.各种不同类型 ...

  7. C Primer Plus 第12章_存储类别、链接和内存管理_代码和练习题

    随机数函数和静态变量 /* r_drive0.c---测试rand0()函数 */ #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> # ...

  8. 存储类、链接、内存管理

    作用域:代码块作用域.函数原型作用域.文件作用域 函数作用域(只适用于goto) 链接:外部链接.内部链接.空链接(代码块作用域.函数原型作用域) 存储时期:静态存储时期.自动动态存储时期 五种存储类 ...

  9. multiprocessing.manager管理的对象需要加锁吗_iOS内存管理布局及管理方案理论篇

    苹果设备备受欢迎的背后离不开iOS优秀的内存管理机制,那iOS的内存布局及管理方案是怎样的呢?我们一起研究下. 内存管理分为五大块 栈区(stack):线性结构,内存连续,系统自己管理内存,程序运行记 ...

最新文章

  1. 聊聊职场那些事儿(转)
  2. Windows 10系统重装U盘启动工具制作方法实例演示,windows11镜像下载地址
  3. centos7 ldap php,php7安装ldap扩展
  4. 直线回归数据 离群值_处理离群值:OLS与稳健回归
  5. 每个程序员都可能犯过的10个错误
  6. 每个Java开发人员应拥有的持久断点
  7. 从前有座山,山里有座庙:递归之法
  8. javaweb解决编码问题_学习编码? 首先,学会解决问题。
  9. C#设计模式——简单工厂模式
  10. 全职宝妈做自媒体怎么样
  11. UNIX编程艺术笔记
  12. 如何用MATLAB编写FIR维纳滤波器,最佳FIR维纳滤波器实现
  13. ruijie交换机lacp动态_vmware esxi 做链路聚合LACP踩坑
  14. Windows安全中心无法使用解决方法
  15. win10 无法安装Hp1020和HP1106打印机问题
  16. 设定自己的100个人生目标
  17. 学会用CUPS管理打印机
  18. win10 自带wi-fi热点速度太慢怎么办_win10wifi热点速度极慢如何解决
  19. RewriteBase: only valid in per-directory config files 解答:
  20. WhatsApp聊天记录迁移新手机,备份如何找回和删除?

热门文章

  1. FormatJS – 让你的 Web 应用程序国际化
  2. jquery ready方法实现原理
  3. hihocoder1543 SCI表示法
  4. linux每天一小步---sed命令详解
  5. maven2 + tomcat6 + eclipse集成配置
  6. 【DeepLearning】Exercise:Learning color features with Sparse Autoencoders
  7. SMO写的查看数据库信息的代码
  8. linux mint 18.3 内核,Linux Mint 18.3 “Sylvia” Cinnamon正式发布上线
  9. matlab tsai手眼标定程序代码_标定系列一 | 机器人手眼标定的基础理论分析
  10. html 访问节点,HTML DOM 访问节点