构建一个arm裸板轻量级的printf
typedef char * va_list;
#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) )
#define va_arg(ap,t) ( *(t *)( ap=ap + _INTSIZEOF(t), ap- _INTSIZEOF(t)) )
#define va_end(ap) ( ap = (va_list)0 )
va_list 相当于char*
_INTSIZEOF(n),是为了保证arm内部的四字节对齐,后面的公式会根据你的输入类型的字节数输出,如果是小于等于4字节,就输出4字节(前提int是4字节),大于4字节就输出他本身的字节数。
va_start(ap,v) ap是输入指针,v是固定参数,调用他后,指针会指向第一个变参(注意不是固参),因为固参和变参的地址是相邻的,固参地址加上固参的类型所占的字节数,就是第一个变参的首地址
va_arg(ap,t) t为当前变参的类型,他会返回变参的值,并把ap指针指向下一个变参。
va_end(ap) 当ap指针用完后,赋值为0,防止野指针。
int printf(const char* format,...)
{
va_list ap;
va_start(ap,format);
myprintf( format , ap );
va_end(ap);
return 0;
}
主要核心函数
static int myprintf( const char* format ,va_list ap)
{
char lead = ' ';
int maxwidth = 0;
for( ; *format !='\0';format++)
{
if( *format !='%' ){
outputc(*format);
continue;
}
maxwidth = 0;
lead = ' ';
format++;
if(*format=='0'){
lead = '0';
format++;
}
while(*format >= '0' && *format <= '9'){
maxwidth *= 10;
maxwidth += (*format - '0');
format++;
}
/* 把对应的字符,映射到对应的功能 */
switch( *format ){
case 'd':OutPutNum( va_arg(ap, int), 10, lead, maxwidth );break;
case 'o':OutPutNum( va_arg(ap, int), 8, lead, maxwidth );break;
case 'u':OutPutNum( va_arg(ap, int), 10, lead, maxwidth );break;
case 'x':OutPutNum( va_arg(ap, int), 16, lead, maxwidth );break;
case 'c':outputc( va_arg(ap, int) ); break;
case 's':OutPutStr( (char*)va_arg(ap, int)); break;
default :outputc(*format); break;
}
}
return 0;
}
static int OutPutNum( long n, int base,char lead,int maxwidth )
{
long m = 0;
unsigned int count = 0,i;
char buffer[MAX_NUMBER_BYTES],*s = buffer + sizeof(buffer);
*--s = '\0';
if(n<0){
m = -n;
}
do{
*--s = AscllNum[m%base];
count++;
}while((m/=base) != 0 );
if( maxwidth && count<maxwidth){
for( i=maxwidth - count;i;i-- ){
*--s = lead;
}
}
if( n<0 ){
*--s = '-';
}
return OutPutStr(s);
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)