在看linux内核kernel.h里面看到这样一个语句:
#define pr_err(fmt, ...) \
eprintf(0, pr_fmt(fmt), ##__VA_ARGS__)
看不懂,于是百度了一下,感谢度娘和博主!
转载于:http://www.cnblogs.com/alexshi/archive/2012/03/09/2388453.html
http://www.cnblogs.com/zhujudah/archive/2012/03/22/2411240.html
首先,#define 是常见的预编译命令,但是假如#放在其它地方用有些巧妙的地方。
1,先来看一个例子:
#include<stdio.h> #include <stdlib.h> #define Func1(x) printf("the square of " #x " is %d.\n",(x)*(x)) int main(void) { int aa=30; Func1(aa); Func1(30); system("pause"); return 0; }
输出:
the square of aa is 900.
the square of 30 is 900.
分析》:#用在预编译语句里面可以把预编译函数的变量直接格式成字符串;注意,不能直接在其它非预编译函数直接使用#aa的形式,假如main函数里面出现printf("the square of " #x " is %d.\n",(x)*(x))是不能通过编译的.
2,
#include<stdio.h> #include <stdlib.h> #define Func3(a) printf("the square of " #a " is %d.\n",b##a) int main(void) { int m=30; int bm=900; Func3(m); //展开后相当于 printf("the square of m is %d.\n",bm); system("pause"); return 0; }
输出:
the square of m is 900.
分析》:## 是宏连接符,作变量链接,Func(a)里面有b##a,也就是说直接连接成b‘a’,Func3(m)对应bm,由于bm在main里面有定义,所以可以打印出来。
3,##__VA_ARGS__这里的‘##’有特殊作用,
__VA_ARGS__是可变参数宏,用法如下:
#define Debug(...) printf(__VA_ARGS__)
使用的时候只需要:
Debug(
"Y = %d\n"
, y);
此时编译器会自动替换成printf("Y = %d\n"
, y
");
对于##__VA_ARGS__的‘##’符号的用法,
例如:#define debug(format, ...) fprintf (stderr, format, ## __VA_ARGS__)
假如可变参数宏为空的时候,”“##”的作用就是让编译器忽略前面一个逗号,不然编译器会报错。
相关推荐
这里,`##__VA_ARGS__`用于将可变参数列表转换为实际参数,从而可以像普通函数调用一样进行传递。 #### 使用注意事项 - **分号吞并问题**:在宏定义中直接包含分号可能会导致意外的副作用。例如,在宏体内直接使用...
本文介绍了C语言中特殊符号 `#` 和 `##` 的用法以及可变参数宏 `__VA_ARGS__` 的应用。通过具体的示例代码,我们可以看到如何利用这些特性来编写更加灵活和强大的宏。`#` 操作符可以帮助我们在运行时生成动态文本...
本文详细介绍了C语言中可变参数函数的实现机制,包括`_va_list`的使用方法,以及如何基于这些机制构建自己的可变参数函数,如简易的`printf`函数。通过理解`_va_list`和`vsnprintf`等函数的工作原理,开发者可以更好...
本文将深入探讨C语言变参函数的设计原理、实现方法以及注意事项。 #### 变参函数概念 变参函数是指在函数定义中允许参数的数量和类型在调用时动态变化的函数。在C语言中,这主要通过省略号(...)实现,使得函数...
下面将详细介绍C语言中可变参数的实现原理、使用方法以及注意事项。 一、可变参数的原理 在C语言中,可变参数的实现基于调用约定(calling convention),通常涉及到两个关键函数:`va_start`、`va_end` 和一个宏 ...
在这个示例中,我们使用了`va_list`、`va_start`、`va_arg`和`va_end`宏来处理可变参数。这些宏提供了访问和遍历可变参数列表的方法。`va_start`初始化`va_list`,`va_arg`用于获取下一个参数,而`va_end`在使用完...
具体做法是通过使用`va_list`类型变量和宏`va_start`, `va_arg`, `va_end`来处理不定数量的参数。例如: ```c #include #include void print_int(int i, ...) { va_list args; va_start(args, i); printf(...
通过本文的学习,我们了解了可变参数列表的基本概念、使用方法和示例。掌握这项技术可以帮助我们编写更灵活、更强大的C语言程序。无论是对于初学者还是有经验的开发者来说,熟悉可变参数列表都是提升C语言编程技能的...
printf("[DEBUG] " fmt "\n", ##__VA_ARGS__); \ } \ } while (0) ``` 这里的`__VA_ARGS__`是可变参数列表,允许传递任意数量的参数。`DEBUG_PRINT`宏在调试模式下会打印出指定格式的调试信息,而在非调试模式下...
然而,这种方法依赖于参数的大小和排列方式,可能在不同的平台上有所不同,因此在实际编程中,通常会使用`va_arg(args, type)`宏来安全地获取变长参数,它会根据指定的类型自动处理大小和对齐问题。 总的来说,...
在C语言中,通常一个函数的参数个数是...以上知识点详细介绍了C语言中如何实现参数个数可变的函数,包括其原理、使用方法、注意事项以及最佳实践。在实际开发中,掌握这部分知识对于编写灵活且健壮的代码是非常重要的。
这里的`__VA_ARGS__`是C99引入的变长参数宏,它可以捕获并替换后面的所有参数。使用这个宏时,你可以这样写: ```c SINGLE_LINE_COMMENT(这是一条测试注释) ``` 编译后,这将被展开为: ```c // 这是一条测试注释...
本项目名为"self_printf.rar_printf_printf函数_self",其核心是实现一个自定义的`printf`函数,帮助初学者理解变长参数列表的原理和用法。下面我们将详细探讨`printf`函数的原理、如何实现自定义的`printf`函数,...
C语言标准提供了一个名为`stdarg.h`的头文件,它包含了一系列处理变长参数的宏和类型,如`va_list`、`va_start`、`va_arg`和`va_end`。这些工具帮助程序员在运行时动态访问和解析变长参数列表。 让我们一步步来解析...
### MSP430G2553上的UART与标准输出函数printf实现 #### 概述 ...通过实现类似`printf`的功能,不仅可以提高开发效率,还可以帮助开发者更好地理解MSP430G2553微控制器的工作原理及其UART接口的使用方法。
4. 使用`va_start`宏初始化`va_list`,然后通过`va_arg`宏逐个访问并处理参数。每个`va_arg`都会从可变参数列表中取出一个参数,类型由提供给`va_arg`的类型决定。 5. 当处理完所有参数后,使用`va_end`宏清理资源。...
NSLog(@"[LogInfo](%d)> %@", [[NSString stringWithUTF8String:__FILE__] lastPathComponent], __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__]); \ #else \ /* nothing */ \ #endif ``` 在这个...