int类型的实参与int*类型的形参不兼容_C++|可变参数函数的实现及其不安全性...

可变参数函数头的一般格式:

return_type function_name(argument_list, ...)

最右边是省略号“...”,省略号“...”的左边必须至少有一形参,必须由靠近省略号“...”的形参来识别省略号“...”表示的形参数量,可以是以下类型:

a 表示长度的int类型;

b 表示哨兵类型的int类型;

c 表示参数类型及数量的字符串,通过解析字符串的字符来解析以后的参数数量及类型;

1 传递一个表示长度的int类型参数

#include #include  // needed to use ellipsis // The ellipsis must be the last parameter// count is how many additional arguments we're passingdouble findAverage(int count, ...){ double sum = 0;  // We access the ellipsis through a va_list, so let's declare one va_list list;  // We initialize the va_list using va_start. The first parameter is // the list to initialize. The second parameter is the last non-ellipsis // parameter. va_start(list, count);  // Loop through all the ellipsis arguments for (int arg=0; arg < count; ++arg) // We use va_arg to get parameters out of our ellipsis // The first parameter is the va_list we're using // The second parameter is the type of the parameter sum += va_arg(list, int);  // Cleanup the va_list when we're done. va_end(list);  return sum / count;} int main(){ std::cout << findAverage(6, 1, 2, 3, 4, 5, 6) << ''; // 3.5 std::cout << findAverage(6, 1.0, 2, 3, 4, 5, 6) << ''; // 1.79766e+008system("pause");return 0;}

在头文件stdarg定义了四个宏:va_list, va_arg, va_start, and va_end,可结合上面的实例并结合栈表示如下:

6f0cc9ce164c7657e08363d348ccb0aa.png

看汇编代码:

8b00e5e4a37be89c03b2fba1a6237732.png

对于findAverage(6, 1.0, 2, 3, 4, 5, 6),并没有得到我们期望的结果,这就是因为其无法完成数据类型的检查,自然也无法做隐式数据类型转换,看汇编代码:

8bb95eecbec265b4b2f1c7381aafb29e.png

在2和6之间压入了3FF00000h和0

00401630 push 2

00401632 push 3FF00000h

00401637 push 0

00401639 push 6

按照IEEE754浮点数算数标准,double浮点数字长64位,一位是符号位,指数长度11,指数偏移量1023,尾数长度52;1.0指数位是0,偏移1023就是10个1,其它位都是0:

0 0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

分成两个32位,后面的32位是0,前面的二进制位用16进制表示成整数就是:3FF00000h,除以6后就得到1.79766e+008。

db7f0d56eb5a7440c983b4471b014df9.png

以上就是可变参数的优势和不安全性。

因为是用宏实现的,所以没有类型检查,且参数数量需要通过其它参数去判断。

2 传递一个哨兵值参数

#include #include  // needed to use ellipsis // The ellipsis must be the last parameterdouble findAverage(int first, ...){// We have to deal with the first number speciallydouble sum = first; // We access the ellipsis through a va_list, so let's declare oneva_list list; // We initialize the va_list using va_start. The first parameter is// the list to initialize. The second parameter is the last non-ellipsis// parameter.va_start(list, first); int count = 1;// Loop indefinitelywhile (1){// We use va_arg to get parameters out of our ellipsis// The first parameter is the va_list we're using// The second parameter is the type of the parameterint arg = va_arg(list, int); // If this parameter is our sentinel value, stop loopingif (arg == -1)break; sum += arg;count++;} // Cleanup the va_list when we're done.va_end(list); return sum / count;} int main(){std::cout << findAverage(1, 2, 3, 4, 5, -1) << '';std::cout << findAverage(1, 2, 3, 4, 5, 6, -1) << '';}

3 传递一个字符串参数

#include #include #include  // needed to use ellipsis // The ellipsis must be the last parameterdouble findAverage(std::string decoder, ...){double sum = 0; // We access the ellipsis through a va_list, so let's declare oneva_list list; // We initialize the va_list using va_start. The first parameter is// the list to initialize. The second parameter is the last non-ellipsis// parameter.va_start(list, decoder); int count = 0;// Loop indefinitelywhile (1){char codetype = decoder[count];switch (codetype){default:case '0':// Cleanup the va_list when we're done.va_end(list);return sum / count; case 'i':sum += va_arg(list, int);count++;break; case 'd':sum += va_arg(list, double);count++;break;}}} int main(){std::cout << findAverage("iiiii
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值