当前位置:网站首页>C语言 可变参数 用法
C语言 可变参数 用法
2022-04-22 07:45:00 【年少生而为人】
前言
在C语言程序中我们涉及的最多的函数就是关于各种 level 的 log 输出的函数实现,这些函数基本都包括 printf() 以及相关的变形体。其中 printf() 的定义为
int printf(const char *format, ...);
该函数是最经典的可变参数函数,它除了有一个参数 format 固定的以外,后面的参数其个数和类型都是可变的,三个点 “…” 作为参数占位符。
一、ANSI C、GNU C
GNU计划,又称革奴计划,是由Richard Stallman在1983年9月27日公开发起的。它的目标是创建一套完全自由的操作系统。它在编写linux的时候自己制作了一个标准成为 GNU C标准。ANSI 美国国家标准协会,它对C做的标准ANSI C标准后来被国际标准协会接收成为 标准C 所以 ANSI C 和标准C(ISO C)是一个概念,其中目前出现的 C标准有:C89、C99、C11 。
总之,可以理解为:ANSI C与ISO C 对于我们开发者来说完全相同,GNU C在 ANSI C基础上增加了一些扩展(具体扩展可自行搜索),即理解为 ISO C == ANSI C < GNU C
二、可变参数宏
在 C99 标准之前,无法在宏定义中使用可变参数定义,C99之后可以通过__VA_ARGS__ 来代替可变参数,即省略号 “…” ,例如:
#define debug(format, ...) \ printf(format, __VA_ARGS__)
在 GNC C 中,宏也可以接收可变数目的参数,就像使用函数一样,例如:
#define pr_debug(fmt,arg...) \
printk(KERN_DEBUG fmt, ##arg)
GNU C/CPP 还支持 ##__VA_ARGS__ ,其中 ## 操作将使预处理器去除掉它前面的那个逗号,因此可变参数宏还可以这样定义,
#define debug(format, ...) \ printf(format, ##__VA_ARGS__)
三、可变参数取参使用方法
1、先定义一个 va_list 类型的变量,比如 ptr,它指向参数列表的首地址;
2、用 va_start 宏初始化 ptr,它的第二个参数是第一个可变参数的前一个参数,即最后一个固定参数;
3、用 va_arg 返回可变的参数,它的第二个参数是要获取的变参类型;
4、可以通过反复调用 va_arg 来依次取得变参值;
5、最后用 va_end 宏结束可变参数的获取。
注意:
(1)定义的函数必须至少有一个固定的参数;因为需要通过固定参数来定位变参的首地址,也就是固定参数地址+sizeof(固定参数类型);
(2)固定参数和可变参数之间可以没有任何关系;虽然经典的printf函数中,第一个固定参数(格式化字符串)包含了后续变量参数的类型,但是这仅仅是函数功能的需要,语法上没有任何要求。
举例如下所示:
#include <stdarg.h>
#include <stdio.h>
void variable_argument(int fix_argument1, ...)
{
va_list ptr;
va_start(ptr, fix_argument1);
int first = va_arg(ptr, int);
char *second = va_arg(ptr, char*);
int third = va_arg(ptr, int);
double four = va_arg(ptr, double);
va_end(ptr);
printf("first is %d, second is %s, third is %d, four is %f\n", first, second, third, four);
return;
}
int main(int argc, char** argv[])
{
variable_argument(1, 2, "hello", 5, 3.1415);
return 0;
}
编译及运行结果如下:
yang@ubuntu:~$ gcc va_func.c
yang@ubuntu:~$ ./a.out
first is 2, second is hello, third is 5, four is 3.141500
版权声明
本文为[年少生而为人]所创,转载请带上原文链接,感谢
https://blog.csdn.net/weixin_45437140/article/details/118399701
边栏推荐
- [paper reading] [3D object detection] voxel set transformer: a set to set approach to 3D object detection from point clouds
- OLED display driver
- Redis is easy to use
- shell脚本学习笔记—循环语句
- 函数指针和指针函数
- Cesium加载地形数据(cesiumlab制作地形数据),从源数据到地形服务
- [no very low code] low code platform development diary, SQL programming of low code platform
- accumulator
- Establishment of golang environment
- Pointer and string
猜你喜欢

Action inattendue dans une instruction SQL

Teach you how to realize the pull-down refresh and pull-up load of recyclerview

129. 求根节点到叶节点数字之和(Medium)

Level 1: create / delete nodes
![[Dahua cloud native] micro service chapter - service mode of five-star hotels](/img/fc/be18f39e4aa653efa8603ab63ff3f1.png)
[Dahua cloud native] micro service chapter - service mode of five-star hotels

Dynamic memory management of C

leaflet、cesium加载百度地图,加载自定义样式百度地图

shell笔记

第2关:子节点创建、列出、删除

Pointer and string
随机推荐
VirtualBox虚拟机(甲骨文Oracle VM )
Common sense and use of Oracle Database
oracle 数据库常识以及使用
Winsock编程接口实验:实现ping
MATLAB提示:要使用 ‘xxx函数‘,则必须授权、安装并启用了以下产品:xxx toolbox
Constructor and toString
String replacement
Use of stream
第2关:多态
kubernetes—实战入门
The PS - EF query process PID in the shell script always returns an exception
liunx基础—zabbix5.0监控系统安装部署
oracle数据库表空间容量查询及扩容
Level 2: ACL access control list
shell脚本学习笔记—循环语句
Level 3: node quota and other commands
面试题 04.03. 特定深度节点链表(Medium)
Client server communication project 2
Pointer and array (detailed operation)
94. Middle order traversal of binary tree (easy)