C语言中函数参数的入栈顺序/变长参数/默认参数提升在可变长参数函数的陷阱

C语言中函数参数的入栈顺序:从右至左。

参数入栈顺序是和具体编译器实现相关的。比如,Pascal语言中参数就是从左到右入栈的,有些语言中还可以通过修饰符进行指定,如Visual C++。即然两种方式都可以,为什么C语言要选择从右至左呢?

C语言支持可变长参数

原因:C语言支持可变长参数.参数的个数可以是不定个,在函数定义的时候用(…)表示.
eg:
printf函数的原型如下:

int printf(const char *format, ...);

注意,采用这种形式定义的可变参数函数,至少需要一个普通的形参,比如上面代码中的*format,后面的省略号是函数原型的一部分。

默认参数提升在可变参数函数的陷阱

在C语言中,调用一个不带原型声明的函数时:调用者会对每个参数执行“默认实际参数提升(default argument promotions)。

同时,对可变长参数列表超出最后一个有类型声明的形式参数之后的每一个实际参数,也将执行上述提升工作。

提升工作如下:
——float类型的实际参数将提升到double
——char、short和相应的signed、unsigned类型的实际参数提升到int
——如果int不能存储原值,则提升到unsigned int

以下摘自《C陷阱与缺陷》
这里有一个陷阱需要避免:
va_arg宏的第2个参数不能被指定为char、short或者float类型。
因为char和short类型的参数会被转换为int类型,而float类型的参数会被转换为double类型 ……
例如,这样写肯定是不对的:
c = va_arg(ap,char);
因为我们无法传递一个char类型参数,如果传递了,它将会被自动转化为int类型。上面的式子应该写成:
c = va_arg(ap,int);
——《C陷阱与缺陷》p164
参考:C语言可变长参数函数与默认参数提升

猜你喜欢

转载自blog.csdn.net/guozhongwei1/article/details/82587831
今日推荐