Linux C编程连载(7) - 变参数实现printf

 【代码清单】

#include <stdio.h>

#define va_list void*
#define va_end(arg)
#define va_start(arg, start) arg = (va_list)(((char *)&(start)) + sizeof(start))
#define va_arg(arg, type) *(type*)arg; arg = (char *)arg +sizeof(type)

char *itoa(int num, char *str, int radix)
{
	char string[] = "0123456789abcdefghijklmnopqrstuvwxyz";
	char *ptr = str;
	int i,j;
	
	while(num)
	{
		*ptr++ = string[ num%radix ];
		num /= radix;

		if(num < radix)
		{	
			*ptr++ = string[num];
			*ptr = '\0';
			break;
		}
	}

	j = ptr - str -1;

	for(i=0; i<(ptr-str)/2; i++)
	{
		int temp = str[i];
		str[i] = str[j];
		str[j--] = temp;
	}

	return str;
}

int mprintf(const char *format, ...)
{
	va_list arg;
	int done = 0;

	va_start(arg, format);

	while(*format != '\0')
	{
		if(*format == '%')
		{
			if(*(format+1) == 'c')
			{
				char c = (char)va_arg(arg,int);
				putc(c,stdout);
			} else if(*(format+1) == 'd'||*(format+1) == 'i')
			{
				char store[20];
				int i = va_arg(arg,int);
				char *str = store;
				itoa(i,store,10);
				while(*str != '\0') putc(*str++,stdout);
			} else if(*(format+1) == 'o')
			{
				char store[20];
				int i = va_arg(arg,int);
				char *str = store;
				itoa(i,store,8);
				while(*str != '\0') putc(*str++,stdout);
			} else if(*(format+1) == 'x')
			{
				char store[20];
				int i = va_arg(arg,int);
				char *str = store;
				itoa(i,store,16);
				while(*str != '\0') putc(*str++,stdout);
			} else if( *(format+1) == 's' )

			{

				char* str = va_arg(arg, char*);

				while( *str != '\0') putc(*str++, stdout);

			}

			format += 2;
				
		} else {

				putc(*format++, stdout);
			}
	}

    va_end (arg);



    return done;
}

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

{ 

    int n = 255;

    char str[] = "hello, world!";





    // Test vprintf function

    mprintf("n = %d\n", n);

    mprintf("n = %i\n", n); 

    mprintf("n = %o\n", n);

    mprintf("n = %x\n", n);

    mprintf("first char = %c\n", str[0]); 

    mprintf("str = %s\n", str);

    mprintf("%s\tn = %d\n", str, n);



    return 0;

}


【解析】

(1)

#define va_start(arg, start) arg = (va_list)(((char *)&(start)) + sizeof(start))

让arg指向start(即format)之后的地址,即可变参数的首地址。

(2)

#define va_arg(arg, type) *(type*)arg; arg = (char *)arg +sizeof(type)

定义了一个va_arg函数,该函数有两个参数,arg和type。并指明了arg是type*类型的指针。该函数的作用是将指针指向下一个可变参数。

【链接】函数定义的两种形式

(1) int func(int a, int b);

(2) int func(a,b) int a, int b;


 

转载请标明出处,仅供学习交流,勿用于商业目的

Copyright @ http://blog.csdn.net/tandesir

 

 

 

你可能感兴趣的:(编程,c,linux,list,String,function)