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

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

作者头像
用户7886150
修改于 2021-02-14 07:05:48
修改于 2021-02-14 07:05:48
8750
举报
文章被收录于专栏:bit哲学院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 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
【C语言】va_list(可变参数处理)
        C 语言中的 va_list 类型允许函数接受可变数量的参数,这在编写需要处理不定数量参数的函数时非常有用。va_list 类型是在 stdarg.h 头文件中定义的,它允许函数处理可变数量的参数。下面我们将详细介绍 va_list 的用法以及实际应用示例。
DevKevin
2024/03/19
1.5K0
C++核心准则ES.34:不要定义C风格的可变参数函数
Not type safe. Requires messy cast-and-macro-laden code to get working right.
面向对象思考
2020/05/20
9690
C语言“…”占位符及可变参数函数
C语言函数的参数传递总是固定了个数,那么有没有传递任意个数参数的方法呢?在C++中,函数重载提供了多种参数传递的解决办法,但也不是任意参数个数。事实上,C语言是提供任意数量参数的解决方案的。
sean.liu
2022/08/03
1.3K0
整理C/C++的可变参数
c语言中使用可变参数最熟悉应该就是printf, 其是通过...来从代码语句中表示可变化的参数表。
Rock_Lee
2020/09/21
5.7K0
可变参数的函数
C语言允许定义参数数量可变的函数,这称为可变参数函数(variadic function)。这种函数需要固定数量的强制参数,后面是数量可变的可选参数。其中,强制参数必须至少一个,可选参数数量可变,类型可变,可选参数的数量由强制参数的值决定。 C 语言中最常用的可变参数函数例子是 printf()和 scanf()。这两个函数都有一个强制参数,即格式化字符串。格式化字符串中的转换修饰符决定了可选参数的数量和类型。 可变参数函数格式:int fun(int a,...)
用户7272142
2023/10/11
4600
go内存分配与垃圾回收
Golang运行时的内存分配算法主要是 TCMalloc算法。 核心思想就是把内存分为多级管理,从而降低锁的粒度。它将可用的堆内存采用二级分配的方式进行管理:每个线程都会自行维护一个独立的内存池,进行内存分配时优先从该内存池中分配,当内存池不足时才会向全局内存池申请,以避免不同线程对全局内存池的频繁竞争。
leobhao
2024/11/29
1620
go内存分配与垃圾回收
C编程基础-基础篇 10
typedef #include <stdio.h> #include <string.h> typedef struct Books { char title[50]; char author[50]; char subject[100]; int book_id; } Book; int main() { Book book; strcpy(book.title, "C 教程"); printf( "书标题 : %s\n", book.tit
未来最可爱的人
2021/02/26
1870
C编程基础-基础篇 10
基于stdarg.h的可变参数函数的用法
在开始学习C语言的函数的时候,我们就知道函数的参数个数应该是在函数声明的时候就指定的,这一点我们没有任何疑问。但是不知道大家有没有注意到我们的printf()函数,他的函数参数理论上并不是确定的,而是随着匹配字符串中的格式控制符的个数控制的。其实当时也没有注意到这一点,到是最近,偶然间看到了《嗨翻C语言》这本书,这里就详细讲解了这种可变参数函数的实现原理,今天考试间隙就顺带学习了一下,其实就是一种方法,知道了就晓得了,也是非常的简单。
mythsman
2022/11/14
6690
有关结构体内重载操作的最详细的讲解~~
C++中,结构体是无法进行==,>,<,>=,<=,!=这些操作的,这也带来了很多不方便的地方,尤其是在使用STL容器的时候,如果我们可以往语句中传入结构体,一些事情将会变得很简单 。 我们来举一个栗子: 身高,分数,序号
杨鹏伟
2020/09/11
5160
C语言-函数的可变形参(不定形参)
在学习C语言函数章节时发现,给函数传入的形参必须和函数定义原型的类型、数量一致才可以正常调用。
DS小龙哥
2022/01/07
1.1K0
C++可变参数
Java中的可变参数其实就是数组,对C++的可变参数比较好奇,所以上网查了资料,了解下!
卡尔曼和玻尔兹曼谁曼
2019/01/25
1.9K0
变长参数探究
变长参数,指的是函数参数数量可变,或者说函数接受参数的数量可以不固定。实际上,我们最开始学C语言的时候,就用到了这样的函数:printf,它接受任意数量的参数,向终端格式化输出字符串。本文就来探究一下,变长参数函数的实现机制是怎样的,以及我们自己如何实现一个变长参数函数。在此之前,我们先来了解一下参数入栈顺序是怎样的。
编程珠玑
2019/09/03
6910
C语言函数不定参数实现方式
函数如何实现不定参数: 由于在C语言中没有函数重载,解决不定数目函数参数问题变得比较麻烦,即使采用C++,如果参数个数不能确定,也很难采用函数重载。对这种情况 ,提出了指针参数来解决问题。 (1)va_list 定义了一个指针arg_ptr, 用于指示可选的参数. (2)va_start(arg_ptr, argN) 使参数列表指针arg_ptr指向函数参数列表中的第一个可选参数,argN是位于第一个可选参数之前的固定参数, 或者说最后一个固定参数.如有一va 函数的声明是void va_test(ch
233333
2018/03/07
2.5K0
C/C++开发基础——可变参数与可变参数模板
1.如果可变参数的参数类型相同,可以使用标准库中的initializer_list。
Coder-ZZ
2023/09/04
8760
C/C++开发基础——可变参数与可变参数模板
【C 语言】C 语言 函数 详解 ( 函数本质 | 顺序点 | 可变参数 | 函数调用 | 函数活动记录 | 函数设计 ) [ C语言核心概念 ]
参数入栈问题 : 函数参数的计算次序是不固定的, 严重依赖于编译器的实现, 编译器中函数参数入栈次序;
韩曙亮
2023/03/27
1.4K0
【C 语言】C 语言 函数 详解 ( 函数本质 | 顺序点 | 可变参数 | 函数调用 | 函数活动记录 | 函数设计 ) [ C语言核心概念 ]
《不定参数与不定宏参数:C++程序员必须掌握的灵活编程技巧》
在 C++ 中,不定参数函数(Variadic Functions) 是一种可以接受数量不确定的参数的函数。这种机制常用于像 printf 这样的标准库函数,也广泛应用于日志系统、格式化输出、通用容器构造等场景
IsLand1314
2025/05/01
700
【网络安全-键盘监视】学会以后去捉弄舍友,看他有了什么不可告人的秘密
同时消息是共享的。 所以可以实现键盘捕获。 同时----键盘又是消息!—消息还会被缓存!
20岁爱吃必胜客
2022/11/13
3290
【网络安全-键盘监视】学会以后去捉弄舍友,看他有了什么不可告人的秘密
C++ 实现可变参数
一般形式都是 type func(char * formatstr,...); 然后通过已有的参数 formatsrr 来推出,后面的参数。 这样写起来的话,就要匹配所有的基本类型,C++提供了3个宏和算法可以简单处理。 这样,通过vsprintf_s就格式化到buf中。 #include <iostream> #include <stdarg.h> void print(char * formatstr,...) { char buf[1024] = {0}; va_lis
forxtz
2020/10/10
5640
变参函数和可变参数宏
前言:此文关于宏的内容摘抄自裸机思维公众号的"为宏证明"系列文章,本文对原文内容做了大量精简,所以难免会有晦涩难懂的地方,想要更深入了解宏的用法,还请移步到裸机思维。
AIoT-KK
2023/02/09
2.2K0
变参函数和可变参数宏
由phithon的一个题目谈可变参数函数
可变参数函数是指参数个数可变的函数,在函数声明和定义的时候并没有明确的指出函数需要的参数个数,具体有多少个参数,是在调用的时候确定的. 可变参数函数并不是什么新奇的东西,早在我们学c语言的时候,就见过,例如我们常用的printf()和scanf()函数. printf() 的函数原型是
用户1879329
2023/02/27
1.3K0
相关推荐
【C语言】va_list(可变参数处理)
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档