转: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):参数数量可变的函数称之为可变参数函数,主要 ...
随机推荐
- APICloud:轻松6步完成App软件开发
现如今,谁不知道App绝对就是OUT,谁不用App简直没法过日子!但是说到App软件开发,不懂编程,不懂技术的人就一脸懵圈.在门外汉来看,App软件开发是一件非常困难的事情,然而APICloud却说, ...
- MVC 区域功能
因为MVC项目是要求都放在固定的文件夹,所以,当项目大的时候,会很不方便管理,所以微软引入的区域的功能 使用方法: 在项目上右击--添加--区域 就会出现Areas的文件夹,里面就是子MVC 渲染: ...
- Nginx配置SSI
一.什么是SSISSI:Server Side Include,是一种基于服务端的网页制作技术,大多数(尤其是基于Unix平台)的web服务器如Netscape Enterprise Server等均 ...
- iOS,html使用交互相关
1.UIWebView加载Html文件 2.UIWebView的委托方法 3.UIWebView和JS交互 4.使用Safari,WebView调试html 5.使用WKWebView加载Html,和 ...
- RDIFramework.NET Web版介绍
RDIFramework.NET Web版介绍 B/S结构(Browser/Server,浏览器/服务器模式),是WEB兴起后的一种网络结构模式,WEB浏览器是客户端最主要的应用软件.这种模式统一了 ...
- Java基础之在窗口中绘图——渐变填充(GradientApplet 1)
Applet程序. import javax.swing.*; import java.awt.*; import java.awt.geom.*; @SuppressWarnings("s ...
- W3cshool之JavaScript基础
1. JavaScript 对大小写敏感 名为 "myfunction"的函数和名为 "myFunction" 的函数是两个不同的函数,同样,变量 & ...
- Oracle中的自动增长字段
Oracle中的自动增长字段 Oracle 中不像MYSQL 和MSSQLServer 中那样指定一个列为自动增长列的方式,不过在Oracle中可以通过SEQUENCE序列来实现自动增长字段. 在Or ...
- windows系统调用 遍历进程的虚拟地址
#include "iostream" #include "windows.h" #include "shlwapi.h" #include ...
- winform下的智能提示框
winform下的智能提示框 最近在搞winform的程序,接触到有些可能以后还会用到的功能,所以写到博客园里去,第一可以加深自己的印象,第二可以在以后再遇到同样问题的时候忘记了可以马上回来看看,第三 ...