Linux Cプログラミング連載(7)-変数パラメータ実装printf
【コードリスト】
【解析】
(1)
argをstart(すなわちformat)の後のアドレスに向けると,パラメータのヘッダアドレスを変えることができる.
(2)
va_が定義されていますarg関数、argとtypeの2つのパラメータがあります.argがtype*タイプのポインタであることを示した.この関数の役割は、ポインタを次の可変パラメータに向けることです.
【リンク】関数定義の2つの形式
(1) int func(int a, int b);
(2) int func(a,b) int a, int b;
転載は出典を明記してください.学習交流だけで、商業目的に使用しないでください.
Copyright @ http://blog.csdn.net/tandesir
#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);
mprintf("n = %i
", n);
mprintf("n = %o
", n);
mprintf("n = %x
", n);
mprintf("first char = %c
", str[0]);
mprintf("str = %s
", str);
mprintf("%s\tn = %d
", 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の2つのパラメータがあります.argがtype*タイプのポインタであることを示した.この関数の役割は、ポインタを次の可変パラメータに向けることです.
【リンク】関数定義の2つの形式
(1) int func(int a, int b);
(2) int func(a,b) int a, int b;
転載は出典を明記してください.学習交流だけで、商業目的に使用しないでください.
Copyright @ http://blog.csdn.net/tandesir