printf 的实现及 可变参数函数研究

代码printf 的实现及 可变参数函数研究上面是一个基本实现。

1.va_start() va_end()函数应用(http://www.daydreaming.com.cn/article/2007-5-31/1838-1.htm

1:当无法列出传递函数的所有实参的类型和数目时,可用省略号指定参数表void foo(...);

void foo(parm_list,...);

2:函数参数的传递原理

函数参数是以数据结构:栈的形式存取,从右至左入栈.eg:

#include

void fun(int a, ...)

{

int temp = &a

temp++;

for (int i = 0; i < a; ++i)

{

cout <<
temp << endl;

temp++;

}

}

int main()

{

int a = 1;

int b = 2;

int c = 3;

int d = 4;

fun(4, a, b, c, d);

system("pause");

return 0;

}

Output::

1

2

3

4

3:获取省略号指定的参数

在函数体中声明一个va_list,然后用va_start函数来获取参数列表中的参数,使用完毕后调用va_end()结束。像这段代码:

void TestFun(charpszDest, int DestLen, const char pszFormat, ...)

{

va_list args;

va_start(args, pszFormat);

_vsnprintf(pszDest, DestLen, pszFormat, args);

va_end(args);

}

4.va_start使argp指向第一个可选参数。va_arg返回参数列表中的当前参数并使argp指向参数列表中的下一个参数。va_end把argp指针清为NULL。函数体内可以多次遍历这些参数,但是都必须以va_start开始,并以va_end结尾。

1).演示如何使用参数个数可变的函数,采用ANSI标准形式

#include 〈stdio.h〉

#include 〈string.h〉

#include 〈stdarg.h〉

/函数原型声明,至少需要一个确定的参数,注意括号内的省略号/

int demo( char, ... );

void main( void )

{

demo("DEMO", "This", "is", "a", "demo!", "");

}

/ANSI标准形式的声明方式,括号内的省略号表示可选参数/

int demo( char msg, ... )

{

/定义保存函数参数的结构/

va_list argp;

int argno = 0;

char para;

/argp指向传入的第一个可选参数,msg是最后一个确定的参数/

va_start( argp, msg );

while (1)

{

para = va_arg( argp, char);

if ( strcmp( para, "") == 0 )

break;

printf("Parameter #%d is: %sn", argno, para);

argno++;

}

va_end( argp );

/将argp置为NULL/

return 0;

}

2)//示例代码1:可变参数函数的使用

#include "stdio.h"

#include "stdarg.h"

void simple_va_fun(int start, ...)

{

va_list arg_ptr;

int nArgValue =start;

int nArgCout=0; //可变参数的数目

va_start(arg_ptr,start); //以固定参数的地址为起点确定变参的内存起始地址。

do

{

++nArgCout;

printf("the %d th arg: %dn",nArgCout,nArgValue); //输出各参数的值

nArgValue = va_arg(arg_ptr,int); //得到下一个可变参数的值

} while(nArgValue != -1);

return;

}

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

{

simple_va_fun(100,-1);

simple_va_fun(100,200,-1);

return 0;

}

3)//示例代码2:扩展——自己实现简单的可变参数的函数。

下面是一个简单的printf函数的实现,参考了中的例子

#include "stdio.h"

#include "stdlib.h"

void myprintf(charfmt, ...) //一个简单的类似于printf的实现,//参数必须都是int 类型

{

char
pArg=NULL; //等价于原来的va_list

char c;



pArg = (char) &fmt //注意不要写成p = fmt !!因为这里要对//参数取址,而不是取值

pArg += sizeof(fmt); //等价于原来的va_start



do

{

c =
fmt;

if (c != '%')

{

putchar(c); //照原样输出字符

}

else

{

//按格式字符输出数据

switch(++fmt)

{

case'd':

printf("%d",
((int)pArg));

break;

case'x':

printf("%#x",
((int)pArg));

break;

default:

break;

}

pArg += sizeof(int); //等价于原来的va_arg

}

++fmt;

}while (
fmt != '');

pArg = NULL; //等价于va_end

return;

}

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

{

int i = 1234;

int j = 5678;



myprintf("the first test:i=%dn",i,j);

myprintf("the secend test:i=%d; %x;j=%d;n",i,0xabcd,j);

system("pause");

return 0;

}

2.vsprintf, vswprintf与printf与函数的可变参数编程 (http://blog.csdn.net/9527/archive/2008/05/19/2457816.aspx

在C语言编程中,我们不可避免的要接触到可变参数函数,对于不支持函数多态的C语言来讲,使用可变参数和宏定义函数是变通的实现函数多态的好方法。在进一步涉及到可变参数函数之前,我们先来看看常用到的两个可变参数的典型,分别是vsprintf和sprintf。一、vsprintf函数

Header File

stdio.h

Category

Memory and String Manipulation Routines

Prototype

int vsprintf(char buffer, const charformat, va_list arglist);

int vswprintf(wchar_t buffer, const wchar_tformat, va_list arglist);

Description

Writes formatted output to a string.

The v...printf functions are known as alternate entry points for the ...printf functions. They behave exactly like their ...printf counterparts, but they accept a pointer to a list of arguments instead of an argument list.

vsprintf accepts a pointer to a series of arguments, applies to each a format specifier contained in the format string pointed to by format, and outputs the formatted data to a string. There must be the same number of format specifiers as arguments.

Return Value

vsprintf returns the number of bytes output. In the event of error, vsprintf returns EOF.

--对照翻译

头文件

stdio.h

分类

内存和字符串操作

函数原型

int vsprintf(char buffer, const charformat, va_list arglist);

int vswprintf(wchar_t buffer, const wchar_tformat, va_list arglist);

描述

写格式化后的输出到一个字符串

v..printf函数族是..print函数族的可替代函数,他们像..printf函数族一样操作,但是他们接受指向参数列表的指针而不是参数列表。

vsprintf接受一个指向一系列可变参数的指针,提供给每一个参数一个包含在form中的格式化定义,并且输出格式化后的数据到一个字符串中,格式定义和参数数量必须相等。

返回值

vsprintf返回输出的字节数目,出错时返回EOF

二、sprintf函数

Header File

stdio.h

Category

Memory and String Manipulation Routines

Prototype

int sprintf(char buffer, const charformat[, argument, ...]);

int swprintf(wchar_t buffer, const wchar_tformat[, argument, ...]);

Description

Writes formatted output to a string.

Note: For details on format specifiers, see printf.

sprintf accepts a series of arguments, applies to each a format specifier contained in the format string pointed to by format, and outputs the formatted data to a string.

sprintf applies the first format specifier to the first argument, the second to the second, and so on. There must be the same number of format specifiers as arguments.

Return Value

On success, sprintf returns the number of bytes output. The return value does not include the terminating null byte in the count.

On error, sprintf returns EOF.

--对照翻译

头文件:

stdio.h

头文件

stdio.h

分类

内存和字符串操作

函数原型

int sprintf(char buffer, const charformat[, argument, ...]);

int swprintf(wchar_t buffer, const wchar_tformat[, argument, ...]);

描述

写格式化后的输出到一个字符串

注意:对于格式化定义规范,参看printf

sprintf接受一系列参数,提供给每一个参数一个格式化定义,并且输出格式化数据到字符串

sprintf提供给首个参数第一个格式化定义,第二个赋予次个格式化定义,格式化定义数量必须和参数数量一致

返回值

成功,返回输出的字节数量,返回值不包含终止null字节的字节数量

错误,返回EOF

为了便于比较这两个函数的使用,下面给出一个程序片段:

char szBuffer[256];

sprintf(szBuffer, "welcome %d, %s", 1, "hi");

ShowMessage(szBuffer);

vsprintf(szBuffer, "welcome %d, %s", 1, "hi"); //<-提示[C++ Error] Unit1.cpp(24): E2034 Cannot convert 'int' to 'void *'

ShowMessage(szBuffer);

原文链接: https://www.cnblogs.com/leaven/archive/2010/03/01/1675746.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/8482

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月6日 下午7:31
下一篇 2023年2月6日 下午7:32

相关推荐