C语言中的可变参数-printf的实现原理
C语言中的可变参数-printf的实现原理
在C/C++中,对函数参数的扫描是从后向前的。C/C++的函数参数是通过压入堆栈的方式来给函数传参数的(堆栈是一种先进后出的数据结构),最先压入的参数最后出来,在计算机的内存中,数据有2块,一块是堆,一块是栈(函数参数及局部变量在这里),而栈是从内存的高地址向低地址生长的,控制生长的就是堆栈指针了,最先压入的参数是在最上面,就是说在所有参数的最后面,最后压入的参数在最下面,结构上看起来是第一个,所以最后压入的参数总是能够被函数找到,因为它就在堆栈指针的上方。printf的第一个被找到的参数就是那个字符指针,就是被双引号括起来的那一部分,函数通过判断字符串里控制参数的个数来判断参数个数及数据类型,通过这些就可算出数据需要的堆栈指针的偏移量了,下面给出printf("%d,%d",a,b);(其中a、b都是int型的)的汇编代码.
在这个函数中,需通过对传入的格式字符串(首地址为lpStr)进行识别来获知可变参数个数及各个可变参数的类型,具体实现体现在for循环中。譬如,在识别为%d后,做的是va_arg ( vap, int ),而获知为%l和%lf后则进行的是va_arg ( vap, long )、va_arg ( vap, double )。格式字符串识别完成后,可变参数也就处理完了。
printf的简单实现:
#include
#include void myitoa(int n, char str[], int radix)
{
int i , j , remain;
char tmp;
i = ;
do
{
remain = n % radix;
if(remain > )
str[i] = remain - + 'A';
else
str[i] = remain + '';
i++;
}while(n /= radix);
str[i] = '\0'; for(i-- , j = ; j <= i ; j++ , i--)
{
tmp = str[j];
str[j] = str[i];
str[i] = tmp;
} } void myprintf(const char *format, ...)
{
char c, ch, str[];
va_list ap; va_start(ap, format);
while((c = *format))
{
switch(c)
{
case '%':
ch = *++format;
switch(ch)
{
case 'd':
{
int n = va_arg(ap, int);
myitoa(n, str, );
fputs(str, stdout);
break;
}
case 'x':
{
int n = va_arg(ap, int);
myitoa(n, str, );
fputs(str, stdout);
break;
}
case 'f':
{
double f = va_arg(ap, double);
int n;
n = f;
myitoa(n, str, );
fputs(str, stdout);
putchar('.');
n = (f - n) * ;
myitoa(n, str, );
fputs(str, stdout);
break;
}
case 'c':
{
putchar(va_arg(ap, int));
break;
}
case 's':
{
char *p = va_arg(ap, char *);
fputs(p, stdout);
break;
}
case '%':
{
putchar('%');
break;
}
default:
{
fputs("format invalid!", stdout);
break;
}
}
break;
default:
putchar(c);
break;
}
format++;
}
va_end(ap);
} int main(void)
{
myprintf("%d, %x, %f, %c, %s, %%,%a\n", , , 3.14, 'B', "hello");
return ;
}
from:http://blog.csdn.net/hackbuteer1/article/details/7558979
C语言中的可变参数-printf的实现原理的更多相关文章
- C语言中的可变参数函数的浅析(以Arm 程序中的printf()函数实现为例) .
我们在C语言编程中会遇到一些参数个数可变的函数,一般人对它的实现不理解.例如Printf(): Printf()函数是C语言中非常常用的一个典型的变参数函数,它 的原型为: int printf( c ...
- C语言中函数可变参数解析
大多数时候,函数中形式参数的数目通常是确定的,在调用时要依次给出与形式参数对应的所有实际参数.但在某些情况下希望函数的参数个数可以根据需要确定.典型的例子有 大家熟悉的函数printf().scanf ...
- C语言中的可变参数函数
C语言编程中有时会遇到一些参数个数可变的函数,例如printf()函数,其函数原型为: int printf( const char* format, ...); 它除了有一个参数format固定以外 ...
- c语言中的# ## 可变参数宏 ...和_ _VA_ARGS_ _
1.#假如希望在字符串中包含宏参数,ANSI C允许这样作,在类函数宏的替换部分,#符号用作一个预处理运算符,它可以把语言符号转化程字符串.例如,如果x是一个宏参量,那么#x可以把参数名转化成相应的字 ...
- 各种语言中的可变参数(java、python、c++、javascript)
索引: java python c++ js 1.Java public class Animal { // 接受可变参数的方法 void eat(String... Objects) { for ( ...
- C函数和宏中的可变参数
一:调用惯例 函数的调用方和被调用方对函数如何调用应该有统一的理解,否则函数就无法正确调用.比如foo(int n, int m),调用方如果认为压栈顺序是m,n,而foo认为压栈顺序是n, m,那么 ...
- Swift语言中为外部参数设置默认值可变参数常量参数变量参数输入输出参数
Swift语言中为外部参数设置默认值可变参数常量参数变量参数输入输出参数 7.4.4 为外部参数设置默认值 开发者也可以对外部参数设置默认值.这时,调用的时候,也可以省略参数传递本文选自Swift1 ...
- C# 中的可变参数方法(VarArgs)
首先需要明确一点:这里提到的可变参数方法,指的是具有 CallingConventions.VarArgs 调用约定的方法,而不是包含 params 参数的方法.可以通过MethodBase.Call ...
- 【转】C,C++中使用可变参数
可变参数即表示参数个数可以变化,可多可少,也表示参数的类型也可以变化,可以是 int,double还可以是char*,类,结构体等等.可变参数是实现printf(),sprintf()等函数的关键之处 ...
随机推荐
- POJ - 3646 The Dragon of Loowater
Once upon a time, in the Kingdom of Loowater, a minor nuisance turned into a major problem. The shor ...
- 终端 10X 工作法(一)
目录 1. Terminal 2. Grep 3. Sed 4. Awk 5. Xargs 6. Find 在 github 上面有一个 700 多人 star 的 repo 叫做 Bash-Onel ...
- 走进JavaWeb技术世界1:JavaWeb的由来和基础知识
本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial 喜欢的话麻烦点下 ...
- 告诉你如何回答"线上CPU100%排查"面试问题
不知道在大家面试中,有没有遇到这个问题: 生产服务器上部署了几个java程序,突然出现了CPU100%的异常告警,你如何定位出问题呢? 这个问题分为两版回答!高调版对不起,我是做研发的,这个问题在生产 ...
- Redis学习三(进阶功能).
一.排序 redis 支持对 list,set 和 zset 元素的排序,排序的时间复杂度是 O(N+M*log(M)).(N 是集合大小,M 为返回元素的数量) sort key [BY patte ...
- Python3字符串常见方法
目录 字符串的进阶使用 格式化输出字符串 当然除了上述方法外,还可以你使用format方法 format方法第二种用法: Python字符串与二进制的转换 字母大写 计字符a出现的次数 输出50个字符 ...
- (未完)经典Web漏洞实战演练靶场笔记
记录下自己写的经典Web漏洞靶场的write up,包括了大部分的经典Web漏洞实战场景,做个笔记. 0x01 任意文件下载漏洞 if(!empty($_GET['filename'])){ $fil ...
- cobalt strike批量发送钓鱼邮件
0×01 利用Cobalt strike生成木马 这里我们生成木马可以用cs带的HTA.OFFICE宏.word宏来使目标上线cs,这里以word宏病毒为例子. 首先我们需要制作一个word宏病毒来进 ...
- Kali桥接模式DHCP自动获取IP失败(VMware)
Kali桥接模式DHCP自动获取IP失败笔者用的是VMware运行Kali Linux,突然发现桥接模式无法上网,只能使用NAT模式.身为有一点点强迫症的人来说,这就很不爽了.于是马上切换为桥接模式, ...
- ubuntu16.04安装zlib
sudo apt-get install zlib1g-dev 下载:libzip-1.0.1.tar.gztar zxcv libzip-1.0.1.tar.gzcd libzip-1.0.1./c ...