前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >c++ 可变参数 默认类型升提升 可变参数陷阱

c++ 可变参数 默认类型升提升 可变参数陷阱

作者头像
用户7886150
修改2021-02-14 15:05:48
7620
修改2021-02-14 15:05:48
举报
文章被收录于专栏:bit哲学院

参考链接: C++ vprintf()

使用vs版本vs2015 64bit win10. 

#include  "stdarg.h"

using namespace std;

#pragma pack(1)

struct St

{

    int a;

    double b;

    float c;

    char d;

    unsigned short e;

    short f;

    int z;

};

#pragma pack()

void fun(int i, ...);

int main(int argc, char *argv[])

{

    double value = 10.1234567891;

    St t;

    t.a = 10;

    t.b = value;

    t.c = 10.2f;

    t.d = 'a';

    t.e = 1232;

    t.f = 342;

    t.z = 11;

    printf("%p,%p,%p,%p,%p,%p,%p\n", &t.a, &t.b, &t.c, &t.d,&t.e,&t.f,&t.z);

    fun(4, t.a, t.b, t.c, t.d,t.e,t.f,t.z);

    char *y = (char*)&t; 

    printf("%d\n", sizeof(St));

    printf("%d,%.10f,%f,%c,%d,%d,%d;\n", t.a, t.b, t.c,t.d,t.e,t.f, t.z);

    vprintf("%d,%.10f,%f,%c,%d,%d,%d;\n", y);//输出错误,y原始的数据不能含有char,short等类型

    return 0;

}

void fun(int i, ...)

{

    va_list li;

    va_start(li,i);

        vprintf("%d,%.10f,%f,%c,%d,%d,%d;\n", li);

    St t;

    //St t = *((St*)li);

    //printf("%d,%.10f,%f,%c;\n", t.a, t.b, t.c, t.z);

    t.a = va_arg(li, int);

    t.b = va_arg(li, double);

        //t.c = va_arg(li, float);

    t.c = va_arg(li, double);

    t.d = va_arg(li, char);

    t.e = va_arg(li, unsigned short);//

    t.f = va_arg(li, short);

    t.z = va_arg(li, int);

    printf("%p,%p,%p,%p,%p,%p,%p\n", &t.a, &t.b, &t.c,&t.d, &t.z);

    va_end(li);

    printf("%d,%.10f,%f,%c,%d,%d,%d;\n", t.a, t.b, t.c, t.d, t.e,t.f,t.z);

如上为vs中的测试代码。 可变参数传递在传递过程中有一个“默认实际参数提升”(参考https://blog.csdn.net/jchnlau/article/details/9466435)的过程 在函数fun中,不定参数中的第3个本来是传递float,但是在这里如果设置解析成float却导致第三个及第三个参数后的所有参数解析都是错误的,如果将第三个参数改为double类型来解析,发现后面的能全部解析正确。 

可以参看 "stdarg.h" 中的宏va_start 和va_arg,va_end在x86的情况下的定义 _INTSIZEOF(n) 作用是将字节数不是sizeof(int)整数倍的类型占用空间改为sizeof(int)的整数倍。所以va_arg对于char,short等实际处理时都是当作int来处理。所以数据在作为不定参数传递到fun函数中时,已经被编译器做过了数据类型提升处理。及char、short,int变成了int,float 变成了double。 

对于vprintf,第二个参数的数据类型要求比较严格。如果希望解析成功,数据类型必须是由int 和double等类型来组装的数据。

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文系转载前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档