: 数据存储在硬盘的时候都是以簇位单位,所以无论文件大小是多少,除非正好是簇大小的倍数,否则文件所占用的最后一个簇或多或少都会产生一些剩余的空间,且这些空间又不能给其它文件使用,即使这个文件只有0字节,也不允许两个文件或两个以上的文件共用一个簇,不然会造成数据混乱。

程序运行的过程:代码->编译(.obj)->链接(.lnk)->可执行程序(.exe/.hex…)
编译属于初加工,类似于宰杀猪的过程
链接则属于深加工,类似于将生猪肉做成一盘菜的过程

编译器的本质, 其实就是将一些复杂逻辑分解成一些简单逻辑。

堆,栈,全局区,常量区,代码区(计算机分配这些区域是为了使用的安全,所以为不同的内存区域设置不同的权限

堆(可读可写): 是大家共有的空间,分全局堆和局部堆。全局堆就是所有没有分配的空间,局部堆就是用户分配的空间。堆在操作系统对进程初始化的时候分配,运行过程中也可以向系统要额外的堆,但是记得用完了要还给操作系统,要不然就是内存泄漏。需要自己手动释放。

栈(可读可写):每个程序运行的时候都会申请一块4GB的内存空间,其中默认生成栈的大小为1024KB。。栈空间不需要在高级语言里面显式的分配和释放。

//这段代码便会出错,发生溢出
int main ()
{char strBuffer[1024 * 1024] = { 0 };return 0;
}
//可以修改为
int main()
{char*  strBuffer=new char[1024*1024];return 0;
}
/*即将数据从栈区转到堆里面,在使用完之后要记得释放空间(delete strBuffer)
*/

全局区(静态区)(static):全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域, 程序结束后由系统释放 。

常量区(只读不写):常量字符串就是放在这里的。 程序结束后由系统释放 。

代码区(可读可写):存放函数体的二进制代码。

int main()
{
00A62280  push        ebp               //将ebp压入堆栈
//ebp:0030f8d8   esp:0030f8c4
00A62281  mov         ebp,esp          //将ESP的值赋给ebp,也就意味着此时堆栈的栈顶和栈底是一样的。
//ebp:0030f8c4   esp:0030f8c4
00A62283  sub         esp,0C0h          //提升栈顶,为后续操作腾出地方
//ebp:0030f8c4   esp:0030f804
00A62289  push        ebx        //ebp:0030f8c4      esp:0030f800
00A6228A  push        esi//ebp: 0030f8c4     esp:0030f7fc
00A6228B  push        edi                 //保护现场//ebp:0030f8c4      esp:0030f7f8
00A6228C  lea         edi,[ebp-0C0h]      //将此时栈顶的地址放入edi中,为后续操作做准备//ebp: 0030f8c4     esp:0030f7f8
00A62292  mov         ecx,30h             //次数 30
//.....
00A62297  mov         eax,0CCCCCCCCh
//..
00A6229C  rep stos    dword ptr es:[edi]  //重复填充cccccccc操作30(H)次printf("I love POEDU!!");//ebp:0030f8c4      esp:0030f7f4
00A6229E  push        offset string "I love POEDU!!" (0A66CB0h)    //将“I love poedu”压入堆栈
//ebp:0030f8c4        esp:0030f7f0
00A622A3  call        _printf (0A6134Dh)                         //调用printf参数
//....
00A622A8  add         esp,4                                       //内平栈
//ebp:0030f8c4:        esp:0030f7f4return 0;00A622AB  xor         eax,eax                              // return 0
}
00A622AD  pop         edi//ebp:0030f8c4          esp:0030f7f8
00A622AE  pop         esi//ebp:  0030f8c4        esp:0030f7fc
00A622AF  pop         ebx                         //恢复现场//ebp:          esp:0030f800
00A622B0  add         esp,0C0h                    //降低堆栈//ebp:0030f8c4          esp:0030f8c4
00A622B6  cmp         ebp,esp                    //     比较栈顶和栈底
00A622B8  call        __RTC_CheckEsp (0A61334h)     //调用 __RTC_CheckEsp检查堆栈空间
00A622BD  mov         esp,ebp
00A622BF  pop         ebp                              //清理工作
00A622C0  ret

函数如何传参:
首先提升堆栈空间为参数腾地方,在这一过程中要保证运行当前指令前的其它参数不变(因为在执行完当前函数后可能还要继续其它的操作),所以要保护现场。
参数一开始是在内存中,在调用函数之前需要将参数传递到堆栈中,而后才会调用函数。

以下是关于堆和栈的详细区别,引用自网络,原文请见 shine_yr的博客

栈(stack)和堆(heap)具体的区别。
(1)在申请方式上,
栈(stack):现在很多人都称之为堆栈,这个时候实际上还是指的栈。它由编译器自动管理,无需我们手工控制。 例如,声明函数中的一个局部变量int b 系统自动在栈中为b开辟空间;在调用一个函数时,系统自动的给函数的形参变量在栈中开辟空间。
堆(heap): 申请和释放由程序员控制,并指明大小。容易产生memory leak。
在C中使用malloc函数。
如:p1 = (char *)malloc(10);
在C++中用new运算符。
如:p2 = new char[20];//(char *)malloc(10);
但是注意p1本身在全局区,而p2本身是在栈中的,只是它们指向的空间是在堆中
(2)申请后系统的响应上,
栈(stack):只要栈的剩余空间大于所申请空间,系统将为程序提供内存,否则将报异常提示栈溢出。
堆(heap): 首先应该知道操作系统有一个记录空闲内存地址的链表,当系统收到程序的申请时,会遍历该链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表中删除,并将该结点的空间分配给程序。另外,对于大多数系统,会在这块内存空间中的首地址处记录本次分配的大小,这样,代码中的delete或free语句才能正确的释放本内存空间。另外,由于找到的堆结点的大小不一定正好等于申请的大小,系统会自动的将多余的那部分重新放入空闲链表中。
(3)申请大小的限制
栈(stack):在Windows下,栈是由高向低地址扩展的数据结构,是一块连续的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,在WINDOWS下,栈的大小是2M(也有的说是1M,总之是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将提示overflow。因此,能从栈获得的空间较小。例如,在VC6下面,默认的栈空间大小是1M(好像是,记不清楚了)。当然,我们可以修改:打开工程,依次操作菜单如下:Project->Setting->Link,在Category 中选中Output,然后在Reserve中设定堆栈的最大值和commit。
注意:reserve最小值为4Byte;commit是保留在虚拟内存的页文件里面,它设置的较大会使栈开辟较大的值,可能增加内存的开销和启动时间。
堆(heap): 堆是向高地址扩展的数据结构,是不连续的内存区域(空闲部分用链表串联起来)。正是由于系统是用链表来存储空闲内存,自然是不连续的,而链表的遍历方向是由低地址向高地址。一般来讲在32位系统下,堆内存可以达到4G的空间,从这个角度来看堆内存几乎是没有什么限制的。由此可见,堆获得的空间比较灵活,也比较大。
(4)分配空间的效率上
栈(stack):栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。但程序员无法对其进行控制。
堆(heap):是C/C++函数库提供的,由new或malloc分配的内存,一般速度比较慢,而且容易产生内存碎片。它的机制是很复杂的,例如为了分配一块内存,库函数会按照一定的算法(具体的算法可以参考数据结构/操作系统)在堆内存中搜索可用的足够大小的空间,如果没有足够大小的空间(可能是由于内存碎片太多),就有可能调用系统功能去增加程序数据段的内存空间,这样就有机会分到足够大小的内存,然后进行返回。这样可能引发用户态和核心态的切换,内存的申请,代价变得更加昂贵。显然,堆的效率比栈要低得多。
(5)堆和栈中的存储内容
栈(stack):在函数调用时,第一个进栈的是主函数中子函数调用后的下一条指令(子函数调用语句的下一条可执行语句)的地址,然后是子函数的各个形参。在大多数的C编译器中,参数是由右往左入栈的,然后是子函数中的局部变量。注意:静态变量是不入栈的。 当本次函数调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最开始存的地址,也就是主函数中子函数调用完成的下一条指令,程序由该点继续运行。
堆(heap):一般是在堆的头部用一个字节存放堆的大小,堆中的具体内容有程序员安排。
(6)存取效率的比较
这个应该是显而易见的。拿栈上的数组和堆上的数组来说:
void main()
{
int arr[5]={1,2,3,4,5};
int *arr1;
arr1=new int[5];
for (int j=0;j<=4;j++)
{
arr1[j]=j+6;
}
int a=arr[1];
int b=arr1[1];
}
上面代码中,arr1(局部变量)是在栈中,但是指向的空间确在堆上,两者的存取效率,当然是arr高。因为arr[1]可以直接访问,但是访问arr1[1],首先要访问数组的起始地址arr1,然后才能访问到arr1[1]。

c语言学习--关于函数的参数传递(汇编和可执行文件)相关推荐

  1. 黑马程序员——c语言学习心得——函数传递二维数组

    黑马程序员--c语言学习心得--函数传递二维数组 -------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 一.定义指针的时候一定要初始化.    变量 ...

  2. 函数的返回值可以不用赋值_C语言学习|函数的应用《一》

    C语言为程序的结构提供了函数和模块 一.函数的定义与使用 <编程之道>中写道:"一个程序应该是灵活自由的.它的子过程就像串在一根线子上的珍珠."子过程在C语言中被称为& ...

  3. C语言学习笔记--函数

    1. C 语言中的函数 (1)函数的由来: 程序 = 数据 + 算法→C 程序 = 数据 + 函数 (2)模块化程序设计 (3)C 语言中的模块 2. 面向过程的程序设计 (1)面向过程是一种以过程为 ...

  4. C语言学习笔记--函数与指针

    1. 函数类型 (1)C 语言中的函数有自己特定的类型,这个类型由返回值.参数类型和参数个数共同决定.如 int add(int i,int j)的类型为 int(int,int). (2)C 语言中 ...

  5. C语言学习笔记——函数

    1.函数的介绍 为完成某一功能的程序指令(语句)的集合,称为函数 在C语言中,函数分为: 自定义函数.系统函数 2.函数的定义 2.1函数的基本语法 返回类型 函数名(形参列表){执行语句...; / ...

  6. R语言学习——plot函数

    plot函数是R语言中画图使用最多的函数,参数也非常之多,简单的总结,之后应该会在学习的过程中不断完善. plot(x, y = NULL ,type = "p", xlim = ...

  7. R语言学习—— ggplot2函数

    最近在自学R语言,但是从纯粹的理论开始学习太慢了而且没有实操不太行,所以目前是在实际应用中查漏补缺,遇到什么临时学什么,然后把笔记都一一记录下啦.分享出来一边是方便自己查找,另一方面也是想方便和我一样 ...

  8. c语言学习-自定义函数并调用将一个字符串中的小写字母改为大写字母(数组元素和数组名作函数参数)

    c语言自定义函数并调用将一个字符串中的小写字母改为大写字母(数组元素和数组名作函数参数) 程序流程图: 代码: #include<stdio.h> char strupr(char ch[ ...

  9. C语言学习记录——팔 函数和递归(1)

    库函数 IO函数 字符串操作函数 (比如strlen) 字符操作函数(比如把大写转小写) 内存操作函数(memset) 时间/日期函数(time) 数学函数(sqrt开平方) 其他库函数 怎样使用文档 ...

最新文章

  1. C++模式学习------策略模式
  2. VBA最常用的基础代码、基础功能写法总结
  3. SAP Spartacus TypeScript和编译后的JavaScript命名规范
  4. POJ 2367 Genealogical tree【拓扑排序】
  5. c语言机器人编程软件,诺宝rc编程软件下载
  6. Xshell家庭版下载
  7. html5----圆形多角
  8. openai-gpt_GPT-3对非技术专业人员意味着什么
  9. CRM用户体验对比(二):导入联系人—— 百会、WorkXP
  10. Linux发行版Ubuntu教程
  11. com.android.stfwd,[原创]360freewifi逆向分析
  12. 。三十功名尘与土,八千里路云和月。莫等闲,白了少年头,空悲切
  13. 是否使用安全模式启动word
  14. 阿里arouter框架使用
  15. 电除尘器 matlab,电除尘用高频高压直流叠加高压脉冲电源的制作方法
  16. 从来只留一场梦 一场春梦成白头 上软疑似解体 忆仙剑而作
  17. 基于SSM的智慧物业系统设计与实现
  18. 人脸识别12-人脸搜索(安防应用)
  19. 一文入门USB设备的驱动编写方法
  20. 20個網頁抓取工具快速抓取網站

热门文章

  1. SSM+冬奥会志愿者招募系统 毕业设计-附源码191621
  2. 起点中文网小说文本分类项目【简易上手的nlp实战项目】
  3. Server com.webank.webase.front.Application Port 5002..Failed
  4. Linux安装-MySQL数据库
  5. 如何在CSDN博客中所贴的代码进行【代码块】显示
  6. form表单使用put方式提交
  7. 想要提升软件测试能力?这12条捷径一定可以帮到你
  8. 网页中商业产品展示页制作方法探讨
  9. js编程黑科技,装逼指南,高逼格代码,让你惊叹不已
  10. 爬虫—新浪微博(登陆访问、cookie访问)