c语言中细节问题
va_list
c语言中va_list用于参数可变的函数中,提供了读取每个参数的方式.
#define _VALIST
typedef char *va_list;
/* 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) (ap = (va_list) NULL)
#define va_start(ap, A) (void) ((ap) = (((char *) &(A)) + (_bnd (A,_AUPBND))))
va_list实际上是一个字符型的指针,va_start会将ap指向A的下一个位置,而va_arg会返回一个T类型的变量,va_end会将ap赋值为NULL.
…
c语言中用…来取消编译器对函数参数个数和类型的检查,这时就利用到了va_list
int sprintf(char *buf, const char *fmt, ...)
{
va_list args;
int i;
va_start(args, fmt);
i = vsprintf(buf, fmt, args);
va_end(args);
return i;
}
##,#等
在c语言的预编译阶段,编译器会对##,#进行替换,替换的规则是
(1) #define P(A) printf("%s: %d\n",#A,A)
(2) #define XNAME(n) x##n
如果调用XNAME(0)就是x0
具体来说,#将一个变量名变为字符串,##将一个字符串和变量值拼接起来.
##__VA_ARGS__
在gcc中存在扩展#define debug(fmt,...) printk(fmt,##__VA_ARGS__ )
其中__VA_ARGS__代表…的参数,加上##是为了防止__VA_ARGS__为空导致编译出错.
#define debug(...) printf(__VA_ARGS__)
__FILE__ 和 __LINE__
__FILE__表示所在文件
__LINE__表示所在文件的行数
__ FUNCTION__表示当前函数
一般用于打印出错消息.
#define dprint(fmt,...) printk("%s,%d,%s:"fmt,\__FILE__\,__LINE__,\__FUNCTION__,##\__VA_ARGS__)
两个连续的”会被消除