转:C语言 可变参数
堆栈一般是怎么压栈处理的
- /*
- * stack space:
- *
- * 参数3 | up
- * 参数2 |
- * 参数1 v down
- */
因为参数是按照从右向左依次压入的,所以后面参数的地址依次根据“%”处理即可。文章中start = (int*) &buffer即获取了最后入栈的参数地址(如果最后一个入栈参数为int类型,自己可以推算出倒数第二个参数的地址。)
【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】
可变参数是C语言编程的一个特色。在我们一般编程中,函数的参数个数都是确定的,事先定下来的。然而就有那么一部分函数,它的个数是不确定的,长度也不一定,这中间有什么秘密吗?
其实,我们可以回忆一下哪些函数是可变参数的函数?其实也就是sprintf、printf这样的函数而已。那么这些函数有什么规律吗?关键就是在这个字符串上面。我们可以举一个例子看看,
- void test()
- {
- printf("%s, value = %d\n", "hello", 10);
- }
test函数里面也就是一个简单的打印函数。那么这个函数有什么特别的地方呢,那就是%s、%d和后面的字符是一一对应的,所以有多少个这样的字符,首参数后面就会剩下多少个参数。那么后面参数的地址怎么获取呢?我们可以回想一下,堆栈一般是怎么压栈处理的,
- /*
- * stack space:
- *
- * 参数3 | up
- * 参数2 |
- * 参数1 v down
- */
因为参数是按照从右向左依次压入的,所以后面参数的地址依次根据“%”处理即可。下面我们就可以自己写一个PrintInt打印int数据的函数,首先创建一个框架,
- void PrintInt(char* buffer, int data, ...)
- {
- return;
- }
然后验证buffer参数中是否有%d,如果存在这样的一个字符,就需要打印一个整数,
- void PrintInt(char* buffer, int data, ...)
- {
- static char space[1024];
- char temp[32];
- int* start;
- int count;
- if(NULL == buffer)
- return;
- memset(space, 0, 1024);
- memset(temp, 0, 32);
- start = (int*) &buffer;
- count = 0;
- while(buffer[count]){
- if(!strncmp(&buffer[count], "%d", strlen("%d"))){
- start ++;
- itoa(*start, temp, 10);
- strcat(space, temp);
- count += 2;
- continue;
- }
- space[strlen(space)] = buffer[count];
- count ++;
- }
- memset(buffer, 0, strlen(buffer));
- memmove(buffer, space, strlen(space));
- return;
- }
为了验证我们的函数是否正确,可以编写测试函数验证一下,
- void display()
- {
- char buffer[32] = {"%d %d %d %d\n"};
- PrintInt(buffer, 1, 2, 3, 4);
- printf(buffer);
- }
转:C语言 可变参数的更多相关文章
- C语言 可变参数
一.基础部分 1.1 什么是可变长参数 可变长参数:顾名思义,就是函数的参数长度(数量)是可变的.比如 C 语言的 printf 系列的(格式化输入输出等)函数,都是参数可变的.下面是 printf ...
- C语言可变参数函数实现原理
一.可变参数函数实现原理 C函数调用的栈结构: 可变参数函数的实现与函数调用的栈结构密切相关,正常情况下C的函数参数入栈规则为__stdcall, 它是从右到左的,即函数中的最右边的参数最先入栈. 本 ...
- 深入C语言可变参数(va_arg,va_list,va_start,va_end,_INTSIZEOF)
一.什么是可变参数 在C语言编程中有时会遇到一些参数个数可变的函数,例如printf(),scanf()函数,其函数原型为: int printf(const char* format,…),int ...
- C语言可变参数在宏定义中的应用
在C语言的标准库中,printf.scanf.sscanf.sprintf.sscanf这些标准库的输入输出函数,参数都是可变的.在调试程序时,我们可能希望定义一个参数可变的输出函数来记录日志,那么用 ...
- C语言可变参数函数的编写
1. 引言 C语言我们接触的第一个库函数是 printf(“hello,world!”);其参数个数为1个. 然后,我们会接触到诸如: printf(“a=%d,b=%s,c=%c”,a,b,c);此 ...
- C语言可变参数va_list
一.什么是可变参数 在C语言编程中有时会遇到一些参数个数可变的函数,例如printf(),scanf()函数,其函数原型为: int printf(const char* format,-) int ...
- C语言可变参数
前段时候在实现利用redis进行的一个数据库比对的功能,稍微去分析了一下redis里面的源代码,然后发现其中的发送命令接口声明如下: void *redisCommand(redisConnect * ...
- c语言可变参数函数
c语言支持可变参数函数.这里的可变指,函数的参数个数可变. 其原理是,一般情况下,函数参数传递时,其压栈顺序是从右向左,栈在虚拟内存中的增长方向是从上往下.所以,对于一个函数调用 func(int a ...
- Go语言 可变参数
最近与同事讨论时,提到Go语言的可变参数,之前没有总结过相关知识点,今天我们介绍一下Go语言的可变参数. 可变参数(Variable Parameters):参数数量可变的函数称之为可变参数函数,主要 ...
随机推荐
- JAVA文件夹导入到Eclipse中方法:
将JAVA文件夹导入到Eclipse中方法:方法一: 直接将java文件夹复制,然后粘贴到项目下:方法二:1.打开eclipse,点击项目的空白处,选择import:2.选择Existing Proj ...
- wordpress搬家到本地URL修改问题
把原来服务器上面的WordPress的数据库和目录文件全部备份下来,在本地用xampp搭了一个服务器,然后将数据库和目录文件全部导入,更改conf文件中的数据库账号密码.没想到本地网站的所有CSS样式 ...
- 换手率的公司使用MQTT的框架
向换手率公司学习.该公司貌似也使用 Golang
- collectionView,tableView的细节处理
1.设置collectionView的高度 1.1为什么要设置高度? collectionView是在tableView的footView里面 , tableView能滚动,collectionVie ...
- Latex常用指令学习
1:\begin{}与\end{}的用法 2:\textcolor{red}{\fangsong\zihao{2}汉字:} 3:\newpage 新的一页 4:\heiti\zihao{4}\bf{ ...
- cookie的三种操作方法
1,jquery.cookie.js 这一篇文章已经写的很详细了: http://www.cnblogs.com/afuge/archive/2013/07/03/3169048.html 2,原生j ...
- js数组去重的4个方法
面试前端必须准备的一个问题:怎样去掉Javascript的Array的重复项, 这个问题看起来简单,但是其实暗藏杀机. 考的不仅仅是实现这个功能,更能看出你对计算机程序执行的深入理解. 我总共总结4种 ...
- cookie导读,理解什么是cookie
一.cookie导读,理解什么是cookie 1.什么是cookie:cookie是一种能够让网站服务器把少量数据(4kb左右)存储到客户端的硬盘或内存.并且读可以取出来的一种技术. 2. ...
- PhoneGap中navigator.notification.confirm的用法详解
navigator.notification.confirm('您确定要退出程序吗?', showConfirm, '退出程序', '确定,取消'); function showConfirm(but ...
- 在linux中访问virtualbox的共享文件夹
1.在客户机里需要安装Virtualbox的增强功能. 2.使用virtualbox的图形界面设置好共享文件夹. 3.假设你设置的共享文件夹的名称是 share,使用如下命令在客户机的linux系统中 ...