C语言培训讲义3.pptVIP

  1. 1、本文档共22页,可阅读全部内容。
  2. 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
  3. 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  4. 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
  5. 5、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
  6. 6、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们
  7. 7、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
  8. 8、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
C语言培训教程 3 张建 2005-3 Budzhang@ 函数值参模型 值参 C语言只有一种“程序结构”:函数 C语言只有值参一种形式的参数 值参和性能 C的参数调用是汇编语言参数调用的自然演进 空间 整型 数组、结构 数组都是用指针传递 结构:早期也是用指针;现代可以是值参 时间 用栈没有用寄存器快 优化时,编译器可能会用寄存器传递参数 数组等用指针 数组参数1 数组参数2 函数调用约定 C规范没有规定函数调用的细节 函数调用一般用栈实现 函数调用约定指汇编级函数细节约定 参数入栈顺序 从左到右 从右到左 栈的维护者 调用者维护 被调用者维护 register关键字 C调用约定 “传统的”C的调用约定 用栈传递参数 参数从右向左压栈 由调用者负责维护栈 嵌入式环境下,可能只用寄存器传递参数 思考:为何从右向左向栈中传递函数参数? 讨论:下面例子运行时栈的内容 Windows调用约定 Windows明确规定了Win32函数的调用约定 VC里为__stdcall 或WINAPI 调用约定: 用栈传递参数 参数从右向左压栈 由被调用者负责清栈 变长参数表函数 最经典的IO函数: printf 函数 简单变长参数例子 实际中参数使用方法 1 传递缓冲区 实际中参数使用方法 2 传递字符串 实际中参数使用方法 3 传递指针数组 传递整数、长整数 用结构参数预留可扩展的机制 栈帧 栈帧也叫过程活动记录,是编译器用来实现过程/函数调用的一种数据结构 从逻辑上讲,栈帧就是一个函数执行的环境:函数参数、函数的局部变量、函数执行完后返回到哪里 … 。 实现上有硬件方式和软件方式(有些体系不支持硬件栈) 栈帧的示意图 多个栈帧的示意图 缓冲区溢出攻击 缓冲区溢出攻击主要是利用栈帧的构成机制,利用疏忽的程序破坏栈帧从而使程序转移到攻击者期望或设定的代码上。 函数间跳转 goto语句只能在函数内部跳转 专有函数setjmp和longjmp实现函数之间的跳转 用于深层错误处理,一般不建议使用 提示:setjmp和longjmp函数的使用可以用来验证是否理解了C的函数调用实现机制 例子 作业 基本 列举用栈和寄存器传递参数的优缺点 编码举例覆盖栈帧 高级 编码试验setjmp和longjmp有什么限制,比如:“全局”变量能回退吗?静态变量能回退吗?局部变量能回退吗?优化对回退有影响吗?怎样样确保局部变量的回退?能从顶层函数回退到底层函数吗? * * int hello(int a) { a = a*2;//对a赋值,不能影响外部变量 return a; } #include stdio.h int main(int argc, char *argv[]) { int a; char sz[100]=hello world\n; a = sizeof(sz); printf(a= %d \n, a); } int hello(char sz[100]) { printf(%s, sz); return sizeof(sz); } #include stdio.h int hello(int a, int b, int c); int main(int argc, char *argv[]) { int a,b,c,n; a=1; b=2; c=3; n = hello(a, b, c); printf(n=%d\n, n); return 0; } int hello(int a, int b, int c) { int n; n = a+b+c; return n; } // printf函数的原型,摘自VC”stdio.h”头文件 int __cdecl fprintf(FILE *, const char *, ...); //下面是调用printf函数的例子代码 printf(“a=%d b=%d\n”, a, b); printf(“name=%s\n”, szname); printf(“hello %s ,%d+%d+%d=%d\n”, name,a,b,c,a+b+c); 使用变长参数函数的最主要的问题就是参数类型不匹配 #include stdio.h #include stdarg.h int hello(char *fmt, ...) { va_list ap; char *p, *sval; int ival; va_start(ap, fmt); for(p = fmt; *p; p++){ switch(*p){ case d: ival = va_arg(ap, int); printf(%d,ival); break; case s: sval = va_arg(ap, char*); printf(%

文档评论(0)

iris + 关注
实名认证
文档贡献者

该用户很懒,什么也没介绍

1亿VIP精品文档

相关文档