美文网首页C语言学习
C语言的可变参数

C语言的可变参数

作者: 榆西带你飞 | 来源:发表于2018-02-28 22:07 被阅读9次

C语言中有些函数使用可变参数,比如常见的int printf( const char* format, ...),第一个参数format是固定的,其余的参数的个数和类型都不固定。

C语言用va_start等宏来处理这些可变参数。这些宏看起来很复杂,其实原理挺简单,就是根据参数入栈的特点从最靠近第一个可变参数的固定参数开始,依次获取每个可变参数的地址。下面我们来分析这些宏。

在stdarg.h头文件中,针对不同平台有不同的宏定义,我们选取X86平台下的宏定义:

typedef char * va_list;

#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )

#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) )

#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )

#define va_end(ap) ( ap = (va_list)0 )

_INTSIZEOF(n)宏是为了考虑那些内存地址需要对齐的系统,从宏的名字来应该是跟sizeof(int)对齐。一般的sizeof(int)=4,也就是参数在内存中的地址都为4的倍数。比如,如果sizeof(n)在1-4之间,那么_INTSIZEOF(n)=4;如果sizeof(n)在5-8之间,那么_INTSIZEOF(n)=8。

为了能从固定参数依次得到每个可变参数,va_start,va_arg充分利用下面两点:

1. C语言在函数调用时,先将最后一个参数压入栈

2. X86平台下的内存分配顺序是从高地址内存到低地址内存

高位地址

第N个可变参数

。。。

第二个可变参数

第一个可变参数 ? ap

固定参数 ? v

低位地址

由上图可见,v是固定参数在内存中的地址,在调用va_start后,ap指向第一个可变参数。这个宏的作用就是在v的内存地址上增加v所占的内存大小,这样就得到了第一个可变参数的地址。

接下来,可以这样设想,如果我能确定这个可变参数的类型,那么我就知道了它占用了多少内存,依葫芦画瓢,我就能得到下一个可变参数的地址。

让我再来看看va_arg,它先ap指向下一个可变参数,然后减去当前可变参数的大小即得到当前可变参数的内存地址,再做个类型转换,返回它的值。

要确定每个可变参数的类型,有两种做法,要么都是默认的类型,要么就在固定参数中包含足够的信息让程序可以确定每个可变参数的类型。比如,printf,程序通过分析format字符串就可以确定每个可变参数大类型。

最后一个宏就简单了,va_end使得ap不再指向有效的内存地址。

看了这几个宏,不禁让我再次感慨,C语言太灵活了,而且代码可以写得非常简洁,虽然有时候让人看得不是很明白,但是一旦明白 过来,你肯定会为它击掌叫好!

其实在varargs.h头文件中定义了UNIX System V实行的va系列宏,而上面在stdarg.h头文件中定义的是ANSI C形式的宏,这两种宏是不兼容的,一般说来,我们应该使用ANSI C形式的va宏。

相关文章

  • C语言----可变参数

    有时,可能会碰到这样的情况,希望函数带有可变数量的参数,而不是预定义数量的参数。C 语言为这种情况提供了一个解决方...

  • C语言可变参数

    要用到的定义和宏 va_list va_start va_arg va_end 具体用法参照下边代码实例 代码实例

  • Lua可变参数

    Lua 函数可以接受可变数目的参数,和 C 语言类似,在函数参数列表中使用...表示函数有可变的参数。 把可变参数...

  • C语言的可变参数

    C语言中有些函数使用可变参数,比如常见的int printf( const char* format, ...),...

  • va_list 可变长参数原理

    在 c 语言中,我们可以使用可变参数来传入多个参数,比如 printf 函数。可变参数的函数需至少定义一个参数值,...

  • C语言可变参数实现

    一.如果我自己来实现printf printf是可变参数的典型列子,他接受一个格式化字符串和不定数量的输出参数,函...

  • 《C语言32—可变参数》

    2019年4月7日星期日 晴 (声明:理论知识部分来自菜鸟教程网站!)今日学习内容: 35、C 可变参数 有时,您...

  • C语言可变数量参数的使用

    C语言支持函数带有可变数量的参数。 可变参数数量的函数格式如下: 函数 func() 最后一个参数写成省略号,即三...

  • C++语言之this原理与友元函数友元类

    1.C++可变参数。java 可变参数 int...C++ 可变参数 ... 需要引入头文件 stdarg.h头文...

  • C语言中的可变参数

    1. 简介 在C语言中可以使用printf进行格式化输出,函数声明如下: 其中第一个参数format代表需要格式化...

网友评论

    本文标题:C语言的可变参数

    本文链接:https://www.haomeiwen.com/subject/ptqwxftx.html