ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

自定义可变参函数

2019-05-08 21:53:43  阅读:193  来源: 互联网

标签:__ va 函数 自定义 list start 可变 printk


文章目录

一、可变参函数

  在C语言编程中,我们经常会遇到一些参数个数可变的函数,如:int printf(const char *format, ...);scanf()等等。它除了第一个参数format固定以外,后面跟着的参数的个数和类型是可变的,其中...称作参数占位符。
  可是上述中的可变参函数是如何对变化的参数进行处理的呢?我们又是否可以编写属于自己的可变参函数呢?当然可以,不过需要首先来认识一下va_list的成员和功能。

1、va_list简介

  va_list是C语言中用于解决变参问题的一组宏,它定义于标准库stdarg.h中,通过命令$ man va_arg也可以从手册中查询到va_list的用法,下面将详细介绍va_list各成员的功能和实现原理。

2、va_list成员

成员 原型 描述 版本
va_start void va_start(va_list ap, last); 初始化va_list类型的变量ap C89
va_arg type va_arg(va_list ap, type); 返回可变参数中类型为type的参数 C89
va_end void va_end(va_list ap); 释放指定的va_list C89
va_copy void va_copy(va_list dest, va_list src); 拷贝va_list的内容 C99

3、va_list原理

  由man手册可知,va_list相关成员定义在stdarg.h文件中,经过查找,该头文件的路径为:/usr/lib/gcc/x86_64-linux-gnu/5/include/stdarg.h。当前PC使用的GCC版本是gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.11)

#define va_start(v,l)   __builtin_va_start(v,l)
#define va_end(v)       __builtin_va_end(v)
#define va_arg(v,l)     __builtin_va_arg(v,l)
#if !defined(__STRICT_ANSI__) || __STDC_VERSION__ + 0 >= 199900L || defined(__GXX_EXPERIMENTAL_CXX0X__)
#define va_copy(d,s)    __builtin_va_copy(d,s)
#endif
#define __va_copy(d,s)  __builtin_va_copy(d,s)

  从上述定义中,可以发现va_list成员都是通过GCC内建函数实现的。这部分对于非编译器研究者的我来说,实在有些晦涩,难以跟踪。因此暂时就先不继续探究了。

4、va_list用法

1)printk函数

  printk()是内核空间的打印函数,其实现中也借助了va_list处理可变参数。printk()原码如下所示:

asmlinkage __visible int printk(const char *fmt, ...)
{
		va_list args;
		int r;
	
		va_start(args, fmt);
		r = vprintk_func(fmt, args);
		va_end(args);
	
		return r;
}
EXPORT_SYMBOL(printk);

具体实现就不再此处分析了,后面会单独分析Linux printk() 实现的原理。

2)自定义函数

/* @file: a.c */
#include <stdio.h>
#include <stdarg.h>

static void show_numbers(int num, ...)
{
        va_list va; 
        va_start(va, num);
        while(num--) {
                printf("%d\n", va_arg(va, int));
        }   
        va_end(va);
}

int main(void)
{
        show_numbers(3, 110, 120, 114);
        return 0;
}

以下是程序运行结果:
a.c

标签:__,va,函数,自定义,list,start,可变,printk
来源: https://blog.csdn.net/weixin_44935940/article/details/89944589

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有