今天再次遇到可变参数的函数的实现,突然发现自己还不是那么清楚。唉,治学不严谨啊。所以这次一定要彻底弄明白。
这篇文章已经说的非常清楚了CSDN C/C++电子杂志第一期 之 可变参数学习笔记 ,所以我就拿今天看到的代码来说说吧
/*****************************************************************************
*
*
* @func void | FormatString | Simple formatted output string routine
*
* @rdesc Returns length of formatted string
*
* @parm unsigned char * | pBuf |
* Pointer to string to return formatted output. User must ensure
* that buffer is large enough.
*
* @parm const unsigned char * | sz,... |
* Format String:
*
* @flag Format string | type
* @flag u | unsigned
* @flag d | int
* @flag c | char
* @flag s | string
* @flag x | 4-bit hex number
* @flag B | 8-bit hex number
* @flag H | 16-bit hex number
* @flag X | 32-bit hex number
*
* @comm
* Same as OutputFormatString, but output to buffer instead of serial port.
*/
unsigned int FormatString (unsigned char *pBuf, const unsigned char *sz, ...)
{
unsigned char c;
va_list vl; //申明一个va_list(char *或者void *)的变量
va_start(vl, sz); //得到最后一个固定参数的地址
szSprintf = pBuf;//char *szSprintf;一个全局的char *
while (*sz) {
c = *sz++;
switch (c) {
case '%':
c = *sz++;
switch (c) { //switch(*++sz)
case 'x': //4-bit hex number
pOutputNumHex(va_arg(vl, unsigned long), 0);
break;
case 'B': //8-bit hex number
pOutputNumHex(va_arg(vl, unsigned long), 2);
break;
case 'H': //16-bit hex number
pOutputNumHex(va_arg(vl, unsigned long), 4);
break;
case 'X': //32-bit hex number
pOutputNumHex(va_arg(vl, unsigned long), 8);
break;
case 'd': //int
{
long l;
l = va_arg(vl, long);
if (l < 0) {
pOutputByte('-');
l = - l;
}
pOutputNumDecimal((unsigned long)l);
}
break;
case 'u': //unsigned
pOutputNumDecimal(va_arg(vl, unsigned long));
break;
case 's': //string
OutputString(va_arg(vl, char *));
break;
case '%': //直接打印出%
pOutputByte('%');
break;
case 'c': //char
c = va_arg(vl, unsigned char);
pOutputByte(c);
break;
default:
pOutputByte(' ');
break;
}
break;
case '/r':
if (*sz == '/n')
sz ++;
c = '/n';
// fall through
case '/n':
pOutputByte('/r');
// fall through
default:
pOutputByte(c);
}
}
pOutputByte(0);
c = szSprintf - pBuf;
szSprintf = 0;
va_end(vl); //良好习惯,vl=NULL,以防止以后的误操作
return (c);
}
/*****************************************************************************
*
*
* @func void | pOutputByte | Sends a byte out of the monitor port.
*
* @rdesc none
*
* @parm unsigned int | c |
* Byte to send.
*
*/
static void
pOutputByte(
unsigned char c
)
{
if (szSprintf)
*szSprintf++ = c;
else
OEMWriteDebugByte(c);
}
/*****************************************************************************
*
*
* @func void | pOutputNumHex | Print the hex representation of a number through the monitor port.
*
* @rdesc none
*
* @parm unsigned long | n |
* The number to print.
*
* @parm long | depth |
* Minimum number of digits to print.
*
*/
static void pOutputNumHex (unsigned long n, long depth)
{
if (depth) {
depth--;
}
if ((n & ~0xf) || depth) {
pOutputNumHex(n >> 4, depth);
n &= 0xf;
}
if (n < 10) {
pOutputByte((unsigned char)(n + '0'));
} else {
pOutputByte((unsigned char)(n - 10 + 'A'));
}
}
/*****************************************************************************
*
*
* @func void | pOutputNumDecimal | Print the decimal representation of a number through the monitor port.
*
* @rdesc none
*
* @parm unsigned long | n |
* The number to print.
*
*/
static void pOutputNumDecimal (unsigned long n)
{
if (n >= 10) {
pOutputNumDecimal(n / 10);
n %= 10;
}
pOutputByte((unsigned char)(n + '0'));
}
/*****************************************************************************
*
*
* @func void | OutputString | Sends an unformatted string to the monitor port.
*
* @rdesc none
*
* @parm const unsigned char * | s |
* points to the string to be printed.
*
* @comm
* backslash n is converted to backslash r backslash n
*/
static void OutputString (const unsigned char *s)
{
while (*s) {
if (*s == '/n') {
OEMWriteDebugByte('/r');
}
OEMWriteDebugByte(*s++);
}
}
/*****************************************************************************
*
*
* @func void | OEMWriteDebugString | Display string to the monitor port.
*
* @parm unsigned short * | str |
* Points to the receiving buffer.
*/
void
OEMWriteDebugString(unsigned short *str)
{
// Loop through text string, sending characters.
//
while (str && *str)
{
OEMWriteDebugByte((unsigned char)*str++);
}
}
/*****************************************************************************
*
*
* @func void | OEMWriteDebugByte | Output byte to the monitor port.
*
* @parm unsigned char *| str |
* Points to the output buffer.
*/
void
OEMWriteDebugByte(UCHAR ch)
{
volatile UART0reg *s2410UART0 = (UART0reg *)UART0_BASE; //对寄存器设置
// Wait for transmit buffer to be empty.
//
while(!(s2410UART0->rUTRSTAT & 0x2))
{
}
s2410UART0->rUTXH = ch; //对寄存器“赋值”
}
int
OEMReadDebugByte()
{
unsigned char ch;
volatile UART0reg *s2410UART0 = (UART0reg *)UART0_BASE;
// Any receive data for us?
//
if (!(s2410UART0->rUTRSTAT & 0x1))
{
ch = OEM_DEBUG_READ_NODATA; // No data.
}
else
{
ch = s2410UART0->rURXH; // Read character.
}
return (ch);
}
关键字:可变参数函数,原理,实现,UART寄存器操作