前言
(1)如果有嵌入式企业需要招聘湖南区域日常实习生,任何区域的暑假Linux驱动实习岗位,可C站直接私聊,或者邮件:zhangyixu02@gmail.com,此消息至2025年1月1日前均有效
(2)最近看到一个问题,关于C语言的函数形参是否能够有默认值的探讨。一开始,我个人认为,C语言的函数形参是不能有默认值的,后面不看不知道,一查吓一跳,发现还真的有这种玩法,在此推荐给大家。
(3)需要注意的是,如下方法要求在C99
标准以上的编译器中使用。
(4)学习本文之前,建议先去了解一下C语言可变参数,这是本人往期讲解可变参数的博客:
<1>如何编写一个可变参数函数?如何让所有单片机的所有串口实现printf函数?
<2>单片机如何实现日志等级打印(适用于多线程,多串口)
理论讲解
(1)如果学习过C++的朋友都知道,在C++中,函数有一个默认参数。在C语言中,我们能否也实现默认参数呢?
“__ VA_ARGS __”宏介绍
(1)我们都知道,C语言的函数存在可变参数,例如经典的printf()函数。有函数有可变参数,那么宏定义有没有可变参数呢?
(2)显然是有了,本文介绍的__ VA_ARGS __
这个宏,就是用来传递可变参数列表的。使用方法如下:
#include <stdio.h>// 简单的可变参数宏,将可变参数打印到控制台
#define PRINT_VARIABLE_ARGS(format, ...) printf(format, __VA_ARGS__)int main()
{// 使用宏打印不定数量的参数PRINT_VARIABLE_ARGS("Hello, %s! The sum is: %d\n", "John", 10+20);return 0;
}
(3)现在我们知道了
__ VA_ARGS __
这个宏的作用,那么又有什么实际意义呢?想要更详细了解的,请看单片机如何实现日志等级打印(适用于多线程,多串口)
“##”的用法
(1)对于
__ VA_ARGS __
这个宏,有一个特点,就是说,如果宏定义的可变列表...
中没有传入任何值。__ VA_ARGS __
就将会是一个空值。
(2)以上面的代码为例子,假如我们可变参数里面不传入任何值,将会出现如下问题
#include <stdio.h>// 简单的可变参数宏,将可变参数打印到控制台
#define PRINT_VARIABLE_ARGS(format, ...) printf(format, __VA_ARGS__)int main()
{// 使用宏打印不定数量的参数PRINT_VARIABLE_ARGS("Hello world");return 0;
}
# 只进行预编译
gcc -E -P -o test.i test.c
# 编译
gcc test.c
(3)为了解决这个问题,我们可以使用
##
这个特殊的操作。如果可变参数被忽略或为空,##
操作将使预处理器(preprocessor)去除掉它前面的那个逗号。例如我们将代码修改成如下,进入编译就能够成功通过。
#include <stdio.h>// 简单的可变参数宏,将可变参数打印到控制台
#define PRINT_VARIABLE_ARGS(format, ...) printf(format, ##__VA_ARGS__)int main()
{// 使用宏打印不定数量的参数PRINT_VARIABLE_ARGS("Hello world");return 0;
}
逗号运算符
(1)我们要实现默认参数,还需要使用到逗号运算符。**逗号运算符的运算优先级会把逗号后边的值输出返回。**例如(123,321),最终输出的是321。
实现一个默认参数
(1)有了上面的基础,我们现在就可以实现一个函数默认参数了。
(2)实现多个形参的默认参数目前还没想到处理办法,现在就只能实现一个默认形参的默认参数。如果有大佬知道如何实现多个形参的默认参数,欢迎赐教。
C代码
(1)首先,我们创建一个C文件,里面输入如下内容。
#include <stdio.h>#define fun(...) _fun((123, ##__VA_ARGS__));void _fun(int val)
{printf("fun input val:%d", val);
}int main()
{fun();printf("\r\n---\r\n");fun(321);
}
(2)执行代码,最终结果如下。
fun input val:123
---
fun input val:321
参考
(1)微信公众号:C语言怎么给函数添加形参的默认值
(2)C站:整理:C/C++可变参数,“## VA_ARGS”宏的介绍和使用
(3)C站:C语言中"#“和”##"的用法
(4)C站:C语言中逗号运算符怎么用?
(5)C站:单片机如何实现日志等级打印(适用于多线程,多串口)
(6)C站:如何编写一个可变参数函数?如何让所有单片机的所有串口实现printf函数?