typedef char * va_list;
//便于移植
#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
//以int的长度,进行四字节对齐。
#define va_start(ap, v) ( ap = (va_list)&v + _INTSIZEOF(v) )
//使ap指向第一个可变参数地址。(va_list)&v得到起始参数的地址。加上_INTSIZEOF(v) 表示第一个可变参数地址。
#define va_arg(ap, t) ( *(t *)( ap=ap + _INTSIZEOF(t), ap- _INTSIZEOF(t)) )
//用逗号表达式,返回ap指向的值。逗号表达式第一句,表示移动指针ap到下一个变量的地址。
#define va_end(ap) ( ap = (va_list)0 )
//释放指针。
unsigned char hex_tab[]={'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
int printf(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
my_printf(fmt, ap);
va_end(ap);
return 0;
}
static int my_printf(const char *fmt, va_list ap)
{
char lead=' ';
int maxwidth=0;
for(; *fmt != '\0'; fmt++)
{
//判断输出数字格式的位数,以便显示时添加‘0’.如果lead不为空,则需要添加显示
lead=' ';
maxwidth=0;
if (*fmt != '%')//直接依次输出
{
outchar(*fmt);
continue;
}
else//next
{
fmt++;
}
//format : %08d, %8d,%d,%u,%x,%f,%c,%s
if(*fmt == '0')
{
lead = '0';
fmt++;
}
while(*fmt >= '0' && *fmt <= '9')
{
maxwidth *=10;
maxwidth += (*fmt - '0');
fmt++;
}
switch (*fmt)
{
case 'd': out_num(va_arg(ap, int), 10, lead, maxwidth); break;
case 'o': out_num(va_arg(ap, unsigned int), 8, lead, maxwidth); break;
case 'u': out_num(va_arg(ap, unsigned int), 10, lead, maxwidth); break;
case 'x': out_num(va_arg(ap, unsigned int), 16, lead, maxwidth); break;
case 'c': outchar(va_arg(ap, int)); break;
case 's': outstring(va_arg(ap, char *)); break;
default: outchar(*fmt); break;
}
}
return 0;
}
//使用硬件等输出设备,输出字符串。与硬件规格书对应
int outchar(int c)
{
while (!(UTRSTAT0 & (1<<2)));
UTXH0 = (unsigned char)c;
return 0;
}
int outstring(const char *s)
{
while (*s != '\0')
{
while (!(UTRSTAT0 & (1<<2)));
UTXH0 = (unsigned char)c;
}
return 0;
}
#define MAX_NUMBER_BYTES 128
//long:防止益处。divide:除数。lead:格式的开头是否需要添加'0'。maxwidth:需要添加多少个'0'。
static int out_num(long input, int divide,char lead,int maxwidth)
{
unsigned long num = 0;//确保输出正数。
char buf[MAX_NUMBER_BYTES];
char *out_string = buf + sizeof(buf);//从末尾往前输出
int str_idx = 0;
int pre_str_idx = 0;
//字符串结束符
*(--out_string) = '\0';
//修正
if (input < 0) num = -input;
else num = input;
//按进制做除法。取余数作为输出字符。
do {
*(--out_string) = hex_tab[num % divide];
str_idx++;
}while ((num /= divide) != 0);
//在前面填充格式'0'
if (maxwidth && str_idx < maxwidth)
{
for (pre_str_idx=maxwidth-str_idx; pre_str_idx; pre_str_idx--)
*(--out_string) = lead;
}
//判断正负
if (input < 0) *(--out_string) = '-';
return outstring(out_string);
}