C语言变参函数的实现,C语言的那些小秘密之变参函数的实现
在学习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语言的那些小秘密之变参函数的实现相关推荐
- c语言 字母 八进制表示'/1011',C语言C语言第一课:C语言概述为什么学习C语言怎样学习C语言.DOC...
[摘要]C语言 第一课: C语言概述 为什么学习C语言 怎样学习C语言 参考资料 ----------------------------------------------------------- ...
- bool类型返回值_Python 到底是强类型语言,还是弱类型语言?
推荐三个网站 1.Python进阶知识: http://python.iswbm.com 2.Python魔法技巧: http://magic.iswbm.com 3.PyCharm 手册: htt ...
- 《C Primer Plus(第6版)中文版》一第1章 初识C语言1.1 C语言的起源
本节书摘来自异步社区<C Primer Plus(第6版)中文版>一书中的第1章,第1.1节,作者 傅道坤,更多章节内容可以访问云栖社区"异步社区"公众号查看. 第1章 ...
- 浅谈python语言_浅谈Python语言基础知识点!
一.Python 语言的简述 Python语言是一种解释型.面向对象的编程语言,是一种开源语言. Python属于动态类定义语言,也是一种强调类型语言. 二.Python 语言的特点 1.简单.高级 ...
- c语言 hello world代码_C语言基础
首先,还是从hello world开始. #include <stdio.h> int main(void) { printf("Hello Worldn"); ret ...
- Swift2.0语言教程之Swift2.0语言中的标准函数
Swift2.0语言教程之Swift2.0语言中的标准函数 Swift2.0中的标准函数 函数除了可以根据参数列表的有无分为无参函数和有参函数,还可以从定义角度分为用户自定义函数和标准函数两种.以上的 ...
- C语言实现易语言变量框,c语言实现简单的易语言
大家熟知的易语言底层其实就是c语言来实现的,c语言的32个关键字加上一些常用的其他,使用#define这种宏定义来实现简单的汉语替换 1.下面就先打开VisualStudio,在头文件目录下新建一个 ...
- 51 时间片系统 纯c语言,51单片C语言学习.doc
51单片C语言学习 51单片机C语言学习第三课 [ 作者:明浩????转贴自:电子制作实验室????点击数:1067????更新时间:2004-10-2????文章录入:admin ]减小字体 增大字 ...
- python程序设计语言是什么类型的语言-Python 是弱类型的语言 强类型和弱类型的语言区别...
Python 是弱类型的语言 在强类型的编程语言中,定义变量时要指明变量的类型,而且赋值的数据也必须是相同类型的,C语言.C++.Java 是强类型语言的代表. 下面我们以 C++ 为例来演示强类型语 ...
- c++强大还是python强大-Python 到底是强类型语言,还是弱类型语言?
0.前言 我在上一篇文章中分析了 为什么 Python 没有 void 类型 的话题,在文章发布后,有读者跟我讨论起了另一个关于类型的问题,但是,我们很快就出现了重大分歧. 我们主要的分歧就在于:Py ...
最新文章
- nagios2------添加监控对象
- WebX5 button tabs的bind-text属性设置
- php执行系统外部命令的四种方法
- Qt学习之路(28): 坐标变换
- 风格迁移--U-GAT-IT模型(ICLR 2020)
- Lync问题解决之前端服务器Wmf2008R2错误
- python爬虫之使用fake_usragent随机更换User_Agent
- matlab画调和曲线图,调和曲线图和轮廓图的比较
- 百度推广怎么做排名靠前网站链接
- 什么是消防产品3C认证?
- 5次Shift破解Win7登录密码
- 微信抖音的服务器,抖音微信登陆未获得权限怎么办
- 榜样的力量——清华大学大数据软件团队2020年度先进个人风采展示
- 服务器域共享文件夹,访问域共享文件夹
- STK Components规格书
- 微信小程序 基础 - 05 (wxml语法:动态数据绑定)
- 浙大计算机学院研究生读书报告,浙江大学工程师学院研究生读书报告撰写要求与模板...
- 游戏盾是怎么保护游戏被攻击的高防IP又是如何防御的
- Python自制小游戏【附源码 直接运行】
- Java 知识点(转)
热门文章
- python模块(一)
- [转载]我们应该更依赖手机一点
- java个人学习笔记:javaBean
- Ubuntu环境搭建系列—JavaEE篇
- FPGA实验四——时间基准电路和带使能的多周期计数器
- 关于数据集 使用PutCollect后m_Recordset-Update();数据集更新报错的问题
- dbcontext mysql_.Net Core 2.0数据库第一种方法Mysql DB的Scaffold-DbContext
- oracle数据库源数据路径,oracle中用什么命令查找数据文件所在路径呢?
- ImageView no longer exists. You should not use this PhotoViewAttacher any more
- RxJava 在Android中的应用(二)