构建一个arm裸板轻量级的printf

构建一个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); //ap指向第一个变参
 myprintf( format , ap );
 va_end(ap);    //释放ap指针
 return 0;
}

主要核心函数

static int myprintf( const char* format ,va_list ap)
{
 char lead = ' ';
 int maxwidth = 0;
 /* format是字符串,一个一个分析字符 */
 for( ; *format !='\0';format++)
 {
  /* 如果字符不是%,就不停输出,是%就跳出 */
  if( *format !='%' ){
   outputc(*format);
   continue;
  }
  /* 每次发现%都要初始化这两个 */
  maxwidth = 0;
  lead = ' ';
/* %后有0的话就是填充字符为0,否则为空格 */
  format++;
  if(*format=='0'){
   lead = '0';
   format++;
  }
  /* 处理%后的数字,为输出宽度,写入maxwidth */
  while(*format >= '0' && *format <= '9'){
   maxwidth *= 10;     //处理两位数三位数。。。。。
   maxwidth += (*format - '0'); //*format - '0'就是数字字符的值
   format++;
  }
  /* 把对应的字符,映射到对应的功能 */
  /* 这个va_arg(ap, int)我觉得可以都是int,他是4字节对齐 */
  /* 只有输出长整型的时候才大于4字节 */
  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;
}
/*
 n:  要输出的参数
 base: 要输出几进制
 lead: 为填充的字符
 maxwidth:输出宽度
 */
 static int OutPutNum( long n, int base,char lead,int maxwidth )
{
 long m = 0;
 unsigned int count = 0,i;
 /* 定义数组空间,用来存储要输出数字的字符 */
 /* 定义指针s,指向数组空间的尾部 */
 char buffer[MAX_NUMBER_BYTES],*s = buffer + sizeof(buffer);
 /* 先让s指向的地址减一,再赋值 (我觉得这不减可以)*/
 *--s = '\0';
 /*确保m为正*/
 if(n<0){
  m = -n;
 }
 /* 把要输出的数字转化为字符,并且更换进制 count来计数这个数有几位*/
 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)}
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

NE666

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值