C语言可变参数
来源:互联网 发布:汉诺塔c语言程序代码 编辑:程序博客网 时间:2024/05/21 09:54
asmlinkage int printk(const char *fmt, ...)
/*
* Use local definitions of C library macros and functions
* NOTE: The function implementations may not be as efficient
* as an inline or assembly code implementation provided by a
* native C library.
*/
#ifndef va_arg
#ifndef _VALIST
#define _VALIST
typedef char *va_list;
#endif /* _VALIST */
/*
* Storage alignment properties
*/
#define _AUPBND (sizeof (acpi_native_int) - 1)
#define _ADNBND (sizeof (acpi_native_int) - 1)
/*
* Variable argument list macro definitions
*/
#define _bnd(X, bnd) (((sizeof (X)) + (bnd)) & (~(bnd)))
#define va_arg(ap, T) (*(T *)(((ap) += (_bnd (T, _AUPBND))) - (_bnd (T,_ADNBND))))
#define va_end(ap) (void) 0
#define va_start(ap, A) (void) ((ap) = (((char *) &(A)) + (_bnd (A,_AUPBND))))
#endif /* va_arg */
* 输出参数ap(类型为va_list): 用于保存函数参数列表中可变参数的首指针(即,可变参数列表)
* 输入参数A: 为函数参数列表中最后一个固定参数
* 输入参数ap(类型为va_list): 可变参数列表,指向当前正要处理的可变参数
* 输入参数T: 正要处理的可变参数的类型
* 返回值: 当前可变参数的值
#include <stdio.h>
#include <stdarg.h> /* 使用va_list、va_start等必须包含的头文件 */
#include <string.h>
/* linux C没有itoa函数,所以要自己写 */
char *itoa(int i, char *str)
{
int mod, div = fabs(i), index = 0;
char *start, *end, temp;
do
{
mod = div % 10;
str[index++] = '0' + mod;
div = div / 10;
}while(div != 0);
if (i < 0)
str[index++] = '-';
str[index] = '\0';
for (start = str, end = str + strlen(str) - 1;
start < end; start++, end--)
{
temp = *start;
*start = *end;
*end = temp;
}
return str;
}
void print(const char *fmt, ...)
{
char str[100];
unsigned int len, i, index;
int iTemp;
char *strTemp;
va_list args;
va_start(args, fmt);
len = strlen(fmt);
for (i=0, index=0; i<len; i++)
{
if (fmt[i] != '%') /* 非格式化参数 */
{
str[index++] = fmt[i];
}
else /* 格式化参数 */
{
switch(fmt[i+1])
{
case 'd': /* 整型 */
case 'D':
iTemp = va_arg(args, int);
strTemp = itoa(iTemp, str+index);
index += strlen(strTemp);
i++;
break;
case 's': /* 字符串 */
case 'S':
strTemp = va_arg(args, char*);
strcpy(str + index, strTemp);
index += strlen(strTemp);
i++;
break;
default:
str[index++] = fmt[i];
}
}
}
str[index] = '\0';
va_end(args);
printf(str);
}
int main()
{
print("Version: %d; Modifier: %s\n", -958, "lingd");
return 0;
}
另一个比较实用的例子:printk只能在内核初始化完控制台(console_init)后才能使用。因此,在Linux内核初始化控制台前,只能使用其它函数来打印内核消息。这些函数有:
void printascii(const char *);
void printhex(unsigned long value, int nbytes);
void printhex2(unsigned char value);
void printhex4(unsigned short value);
void printhex8(unsigned long value);
这些函数都是用汇编实现的,并直接从低层操作s3c2410的串口,并显示信息。因此不需要等到console_init后就可以显示信息。
为了使用这些函数,需要特性的内核选项支持:make menuconfig
Kernel hack ->
[*]Kernel low-level debugging functions
[*]Kernel low-level debugging messages via S3C UART
(0)S3C UART to use for low-level debug
但是,这些函数并没有printk功能那么强大,支持可变参数,支持格式化字符串。为了在Linux内核初始化控制台前,能使用了一个类似于printk的函数,我们将printascii函数封装到新函数debug里:
extern void printascii(const char *);
static void debug(const char *fmt, ...)
{
va_list va;
char buff[256];
va_start(va, fmt);
/* 函数vsprintf:用于输出格式化字符串到缓冲区
* 输出参数buff:用于保存结果的缓冲区
* 输入参数fmt: 格式化字符串
* 输入参数va: 可变参数列表
* 返回值: 实际输出到缓冲区的字符数
*/
vsprintf(buff, fmt, va);
va_end(va);
printascii(buff);
}
- c语言可变参数
- C语言可变参数
- C语言可变参数
- C语言可变参数
- c语言可变参数
- c语言可变参数
- C语言可变参数
- C语言可变参数
- C语言可变参数
- c 语言可变参数
- c语言可变参数
- c语言 可变参数
- c语言可变参数 ...
- c语言可变参数
- C 语言 可变参数
- C语言可变参数
- C语言可变参数
- c语言可变参数
- 钻牛角尖系列之JVM(二)—对象是怎么来的?
- 摄像头跟随
- Android中级:多渠道打包
- emoji 表情图片解决方法
- 堆排序的实例化(详细过程)
- C语言可变参数
- ECMAScript6(ES6)标准之函数扩展特性箭头函数、Rest参数及展开操作符
- Win7下Git的安装
- 百度地图demo(Android Studio)
- eclipse中设置包的分成显示,看起来比较有层次感
- MySql查询入门
- heroku
- 融云项目经验总结-头像和昵称显示/badge显示
- 如何封装一个自己的mvc框架(一)