在学习C语言的过程中我们可能很少会去写变参函数,印象中大学老师好像也没有提及过,但我发现变参函数的实现很巧妙,所以还是特地在此分析下变参函数的实现原理。无需标准C的支持,我们自己写代码来实现。本文引用地址:http://www.eepw.com.cn/article/270588.htm

先来看看一个实现代码:

#include

#define 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(int nr, ...)

{

int i = 0;

int result = 0;

va_list arg = NULL;

va_start(arg, nr);

for(i = 0; i < nr; i++)

{

result += va_arg(arg, int);

}

return result;

}

int main(int argc, char* argv[])

{

printf("%d\n", sum(4, 100,100,100,100));

printf("%d\n", sum(3, 200, 200, 200));

return 0;

}

运行结果如下:

#define va_list void*通过这句代码我们实现了定义va_list是一个指针,参数类型不定,它可以指向任意类型的指针。为了让arg指向第一个可变参数,我们用nr的地址加上nr的数据类型大小就行了,采用如下的定义可以实现。

#define va_start(arg, start) arg = (va_list)(((char*)&(start)) + sizeof(start)) 。

通过(((char*)&(start)) + sizeof(start)) 可以得到第一个可变参数的地址,再将其强制转换为va_list类型。

成功取出了第一个可变参数后,接下来的任务就是继续取出可变参数,方法跟上面求第一个可变参数的方法一样,通过arg = (char*)arg + sizeof(type);来实现让arg指向下一个可变参数,type为可变参数的类型,通过这种方法可以一一取出可变参数。

在这里顺便给出上面实现代码的汇编代码,有兴趣的可以读读,加深下对于底层汇编代码的阅读能力。

.file "varargs.c"

.text

.globl sum

.type sum, @function

sum:

pushl %ebp

movl %esp, %ebp

subl $16, %esp

movl $0, -4(%ebp)

movl $0, -8(%ebp)

movl $0, -12(%ebp)

leal 12(%ebp), %eax

movl %eax, -12(%ebp)

movl $0, -4(%ebp)

jmp .L2

.L3:

movl -12(%ebp), %eax

movl (%eax), %eax

addl %eax, -8(%ebp)

addl $4, -12(%ebp)

addl $1, -4(%ebp)

.L2:

movl 8(%ebp), %eax

cmpl %eax, -4(%ebp)

jl .L3

movl -8(%ebp), %eax

leave

ret

.size sum, .-sum

.section .rodata

.LC0:

.string "%d\n"

.text

.globl main

.type main, @function

main:

pushl %ebp

movl %esp, %ebp

andl $-16, %esp

subl $32, %esp

movl $100, 16(%esp)

movl $100, 12(%esp)

movl $100, 8(%esp)

movl $100, 4(%esp)

movl $4, (%esp)

call sum

movl $.LC0, %edx

movl %eax, 4(%esp)

movl %edx, (%esp)

call printf

movl $200, 12(%esp)

movl $200, 8(%esp)

movl $200, 4(%esp)

movl $3, (%esp)

call sum

movl $.LC0, %edx

movl %eax, 4(%esp)

movl %edx, (%esp)

call printf

movl $0, %eax

leave

ret

.size main, .-main

.ident "GCC: (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2"

.section .note.GNU-stack,"",@progbits

C语言变参函数的实现,C语言的那些小秘密之变参函数的实现相关推荐

  1. c语言 字母 八进制表示'/1011',C语言C语言第一课:C语言概述为什么学习C语言怎样学习C语言.DOC...

    [摘要]C语言 第一课: C语言概述 为什么学习C语言 怎样学习C语言 参考资料 ----------------------------------------------------------- ...

  2. bool类型返回值_Python 到底是强类型语言,还是弱类型语言?

    推荐三个网站 1.Python进阶知识: http://python.iswbm.com  2.Python魔法技巧: http://magic.iswbm.com 3.PyCharm 手册: htt ...

  3. 《C Primer Plus(第6版)中文版》一第1章 初识C语言1.1 C语言的起源

    本节书摘来自异步社区<C Primer Plus(第6版)中文版>一书中的第1章,第1.1节,作者 傅道坤,更多章节内容可以访问云栖社区"异步社区"公众号查看. 第1章 ...

  4. 浅谈python语言_浅谈Python语言基础知识点!

    一.Python 语言的简述 Python语言是一种解释型.面向对象的编程语言,是一种开源语言. Python属于动态类定义语言,也是一种强调类型语言. 二.Python 语言的特点 1.简单.高级 ...

  5. c语言 hello world代码_C语言基础

    首先,还是从hello world开始. #include <stdio.h> int main(void) { printf("Hello Worldn"); ret ...

  6. Swift2.0语言教程之Swift2.0语言中的标准函数

    Swift2.0语言教程之Swift2.0语言中的标准函数 Swift2.0中的标准函数 函数除了可以根据参数列表的有无分为无参函数和有参函数,还可以从定义角度分为用户自定义函数和标准函数两种.以上的 ...

  7. C语言实现易语言变量框,c语言实现简单的易语言

    大家熟知的易语言底层其实就是c语言来实现的,c语言的32个关键字加上一些常用的其他,使用#define这种宏定义来实现简单的汉语替换 1.下面就先打开VisualStudio,在头文件目录下新建一个 ...

  8. 51 时间片系统 纯c语言,51单片C语言学习.doc

    51单片C语言学习 51单片机C语言学习第三课 [ 作者:明浩????转贴自:电子制作实验室????点击数:1067????更新时间:2004-10-2????文章录入:admin ]减小字体 增大字 ...

  9. python程序设计语言是什么类型的语言-Python 是弱类型的语言 强类型和弱类型的语言区别...

    Python 是弱类型的语言 在强类型的编程语言中,定义变量时要指明变量的类型,而且赋值的数据也必须是相同类型的,C语言.C++.Java 是强类型语言的代表. 下面我们以 C++ 为例来演示强类型语 ...

  10. c++强大还是python强大-Python 到底是强类型语言,还是弱类型语言?

    0.前言 我在上一篇文章中分析了 为什么 Python 没有 void 类型 的话题,在文章发布后,有读者跟我讨论起了另一个关于类型的问题,但是,我们很快就出现了重大分歧. 我们主要的分歧就在于:Py ...

最新文章

  1. nagios2------添加监控对象
  2. WebX5 button tabs的bind-text属性设置
  3. php执行系统外部命令的四种方法
  4. Qt学习之路(28): 坐标变换
  5. 风格迁移--U-GAT-IT模型(ICLR 2020)
  6. Lync问题解决之前端服务器Wmf2008R2错误
  7. python爬虫之使用fake_usragent随机更换User_Agent
  8. matlab画调和曲线图,调和曲线图和轮廓图的比较
  9. 百度推广怎么做排名靠前网站链接
  10. 什么是消防产品3C认证?
  11. 5次Shift破解Win7登录密码
  12. 微信抖音的服务器,抖音微信登陆未获得权限怎么办
  13. 榜样的力量——清华大学大数据软件团队2020年度先进个人风采展示
  14. 服务器域共享文件夹,访问域共享文件夹
  15. STK Components规格书
  16. 微信小程序 基础 - 05 (wxml语法:动态数据绑定)
  17. 浙大计算机学院研究生读书报告,浙江大学工程师学院研究生读书报告撰写要求与模板...
  18. 游戏盾是怎么保护游戏被攻击的高防IP又是如何防御的
  19. Python自制小游戏【附源码 直接运行】
  20. Java 知识点(转)

热门文章

  1. python模块(一)
  2. [转载]我们应该更依赖手机一点
  3. java个人学习笔记:javaBean
  4. Ubuntu环境搭建系列—JavaEE篇
  5. FPGA实验四——时间基准电路和带使能的多周期计数器
  6. 关于数据集 使用PutCollect后m_Recordset-Update();数据集更新报错的问题
  7. dbcontext mysql_.Net Core 2.0数据库第一种方法Mysql DB的Scaffold-DbContext
  8. oracle数据库源数据路径,oracle中用什么命令查找数据文件所在路径呢?
  9. ImageView no longer exists. You should not use this PhotoViewAttacher any more
  10. RxJava 在Android中的应用(二)