C语言的那些小秘密之变参函数的实现_第1页
已阅读5页,还剩3页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、c语言的那些小秘密之变参函数的实现在学习的过程中我们可能很少会去写变参函数,印象中高校教师好似也没有提及过,但我发觉变参函数的实现很巧妙,所以还是专门在此分析下变参函数的实现原理。无需标准c的支持,我们自己写代码来实现。先来看看一个实现代码:includedefine va_list void*define va_arg(arg, type) *(type*)arg; arg = (char*)arg + sizeof(type);define va_start(arg, start) arg = (va_list)(char*)&(start) + sizeof(start)int sum(

2、int nr, .)int i = 0;int result = 0;va_list arg = null;va_start(arg, nr);for(i = 0; idefine va_list void*通过这句代码我们实现了定义va_list是一个指针,参数类型不定,它可以指向随意类型的指针。为了让arg指向第一个可变参数,我们用nr的地址加上nr的数据类型大小就行了,采纳如下的定义可以实现。define va_start(arg, start) arg = (va_list)(char*)&(start) + sizeof(start) 。通过(char*)&(start) + siz

3、eof(start) 可以得到第一个可变参数的地址,再将其强制转换为va_list类型。胜利取出了第一个可变参数后,接下来的任务就是继续取出可变参数,办法跟上面求第一个可变参数的办法一样,通过arg = (char*)arg + sizeof(type);来实现让arg指向下一个可变参数,type为可变参数的类型,通过这种办法可以一一取出可变参数。在这里顺便给出上面实现代码的汇编代码,有爱好的可以读读,加深下对于底层汇编代码的阅读能力。.file varargs.c.text.globl sum.type sum, functionsum:pushl %ebpmovl %esp, %ebpsu

4、bl $16, %espmovl $0, -4(%ebp)movl $0, -8(%ebp)movl $0, -12(%ebp)leal 12(%ebp), %eaxmovl %eax, -12(%ebp)movl $0, -4(%ebp)jmp .l2.l3:movl -12(%ebp), %eaxmovl (%eax), %eaxaddl %eax, -8(%ebp)addl $4, -12(%ebp)addl $1, -4(%ebp).l2:movl 8(%ebp), %eaxcmpl %eax, -4(%ebp)jl .l3movl -8(%ebp), %eaxleaveret.siz

5、e sum, .-sum.section .rodata.lc0:.string %dn.text.globl main.type main, functionmain:pushl %ebpmovl %esp, %ebpandl $-16, %espsubl $32, %espmovl $100, 16(%esp)movl $100, 12(%esp)movl $100, 8(%esp)movl $100, 4(%esp)movl $4, (%esp)call summovl $.lc0, %edxmovl %eax, 4(%esp)movl %edx, (%esp)call printfmo

6、vl $200, 12(%esp)movl $200, 8(%esp)movl $200, 4(%esp)movl $3, (%esp)call summovl $.lc0, %edxmovl %eax, 4(%esp)movl %edx, (%esp)call printfmovl $0, %eaxleaveret.size main, .-main.ident gcc: (/linaro 4.5.2-8ubuntu4) 4.5.2.section .note.gnu-stack,progbits树莓派文章专题:树莓派是什么?你不知道树莓派的学问和应用其中有几条命令在此讲解下。leave命令

7、所做的操作相当于如下两条命令:movl %ebp, %esppopl %ebpret命令所做的操作相当于如下命令:pop %eip假如有对at&t汇编语规矩则不懂的,可以看看我前面写的那篇文章。到这儿为止是乎应当是说结束的时候了,但是精心的读者可能发觉了一个问题,就是我们在最初给出的代码部分有一句红色标志的代码,如下:define va_start(arg, start) arg = (va_list)(char*)&(start) + sizeof(start)为什么要把这句代码单独拿出来讲解呢,绝对是有缘由的,由于(char*)&(start) +sizeof(start)这句代码的特别性

8、在于用法了(char*)举行强制转换,在这里为什么不用法(int*)举行强制转换呢,如改为如下代码:includeincludedefine va_list void*define va_arg(arg, type) *(type*)arg; arg = (char*)arg + sizeof(type);define va_start(arg, start) arg = (va_list)(int*)&(start) + sizeof(start) /修改为(int*)int sum(int nr, .)int i = 0;int result = 0;va_list arg = null;

9、va_start(arg, nr);for(i = 0; i明显运行结果是错误的,为什么会浮现这样的错误呢,我们暂且不分析,先来看看我们接下来做的修改:includeincludedefine va_list void*define va_arg(arg, type) *(type*)arg; arg = (char*)arg + sizeof(type);define va_start(arg, start) arg = (va_list)(int*)&(start) + sizeof(start)/4) /注重对照红色部分的变幻int sum(int nr, .)int i = 0;int

10、 result = 0;va_list arg = null;va_start(arg, nr);for(i = 0; i运行结果正确。现在来分析下为什么会浮现这两种结果呢,看看下面我给出的这个图解和代码应当就能够很清晰的理解为什么会浮现以上的两种运行结果了。代码如下:includeint main()int a = 12;int *p_int = &a;char *p_char = (char*)&a;printf( %d t, sizeof(char);printf( %d t, sizeof(int);printf( %d t, p_int+1);printf( %d t, p_char

11、+1);return 0;运行结果为:修改以上红色部分的代码,得到如下代码:includeint main()int a = 12;int *p_int = &a;char *p_char = (char*)&a;printf( %d t, sizeof(char);printf( %d t, sizeof(int);printf( %d t, p_int+1);printf( %d t, p_char+4);return 0;注重对照前后代码的变幻部分!运行结果如下:首先看看给出的图,int指针所指向的单元占有四个字节的空间,而char指针所指向的单元只占有一个字节的空间。所以假如是整形指针想要取下一个参数,只需加1,但是假如是char指针,假如当前参数是int型,那么想要取下一个参数就要加4才干实现。但是值得注重的是,int*和char*所占的存储单元都是4个字节,这是由我们所用法的32位计算机本身确定的。为了加深大家的印象,专门给出如下代码:includeint main()int a = 12;int *p_int = &a;char *p_char = (char*)&a;printf( %d t, si

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论