Printf可变參数使用
參考文档: http://bbs.csdn.net/topics/70288067
Owed by: 春夜喜雨 http://blog.csdn.net/chunyexiyu 转载请标明来源
本文的二个重点:
1. 可变參数实际上通过首个參数的地址来获取其他參数的地址。由于是顺序存储传过来的
1. 可变參数为了处理方便。全部的浮点型都是依照double型压栈。
因此,像printf採用的可变參数,它直接使用%f显示double型。不须要管float型。
关注printf的精度,须要先关注printf的实现,关于printf的实现,我们就要关注一下可变參数的实现:
变參的一个例了:
|
void { va_list argptr; va_start(argptr, if (type == 0 ) { int n = va_arg( printf( "%d\n", } else if (type == 1) { double d = printf( "%f\n", } else {} } 測试: float testIntAndFloat(0, testIntAndFloat(1, 输出: 123 12345.0000 |
查看变參相关的定义:
typedef
char * va_list;
#define
va_start (ap,v) (
ap = (va_list)_ADDRESSOF(v) +
_INTSIZEOF(v) )
#define
_ADDRESSOF(v) ( &reinterpret_cast<constchar &>(v))
#define
_INTSIZEOF(n) ( (sizeof(n) +
sizeof(int) - 1)& ~(sizeof(int)- 1) )
#define
va_arg (ap,t) ( *(t*)((ap +=
_INTSIZEOF(t)) -
_INTSIZEOF(t)) )
//_ADDRESSOF(v):获取v的地址,并转为char*型
//_INTSIZEOF(n):实现4字节对齐
//va_start (ap,v):
获取參数v之后的地址
//va_arg(av, t): ap地址向后移t类型size,并返回ap地址之前t类型变量的值
看一个输出%d的样例:
|
__int64 printf("%d,%d \n",i, 结果为: 123456, 0 printf("%d,%d,%d,%d \n",i, 结果为: 123456,0,123456,0 printf("%lld,%lld \n",i, 结果为: 123456, 123456 |
从上面的内容能够看出来:
%d时,每次读取的位数是4位,而int64有8位。所以假设使用%d的话,分两次读取完。
(因为是little endian。先读低位,再读高位,先读到123456。再读到0)
再看输出%f的样例
|
float double fd = f; double printf("%f\%f\n%f\n",f,fd, 结果为: 1234567939550609400.0000 1234567939550609400.0000 1234567890123456800.0000 |
能够看出:
float实际是被转成double型存储显示的
(float的精底一般是6-7位。double是15-16位,printf的时候,显示的位数是按double算的。)
再看这个样例,执行时观察内存信息:
(观察内存方式: VC->调试->窗体->内存)
|
void { va_list argptr; va_start(argptr, for (int i=0; { int* pNumber = (int*)argptr; float* pFloat = (float*)argptr; va_arg(argptr, printf(("\naddrss:%d int value: %d float value: %f"), } } void { printf("\nf1=%f", printf(("\naddrss of arg(int): %x, value: %d"), &n1, printf(("\naddrss of arg(float): %x, value: %d|%d, float:%f"), &f1, printf(("\naddrss of arg(double): %x, value: %d|%d, float:%f"), &d1, printf(("\naddrss of arg(char): %x, value: %d"), &c1, printf(("\naddrss of arg(bool): %x, value: %d"), &b1, printf(("\naddrss of arg(short): %x, value: %d"), &s1, printf(("\naddrss of arg(__int64): %x, value: %d"), &n2, printf(("\naddrss of arg(int): %x, value: %d"), &n3, testArgs(n1, } |
当按函数定參參数形式传递TestFuncArgs时:
Int/char/bool/short占用4字节
Float占用4字节
Double点用8字节
__int64占用8字节
内存中连续显示
1f 00 00 00 --int
00 00 f8 41 --float
00 00 00 00 00 00 3f 40 --double
1f 00 00 00 --char
01 00 00 00 --bool
1f 00 00 00 --short
1f 00 00 00 00 00 00 00
–int64
1f 00 00 00 00 00 -- int
当採用不定參数传递testArgs时:
其他均不变,但float为8字节存储,这个是须要很注意的一个事情。
使用%d打印时,仅仅会取4字节,须要使用两个%d%d才干打印一个float。
内存中连续显示
1f00 00 00 -- int
00 00 00 00 00 00 3f 40 --float
00 00 00 00 00 00 3f 40 --double
1f 00 00 00 --char
01
00 00 00 --bool
1f 00 00 00 --short
1f 00 00 00 00 00 00 00
–int64
Printf可变參数使用的更多相关文章
- C语言利用va_list、va_start、va_end、va_arg宏定义可变參数的函数
在定义可变參数的函数之前,先来理解一下函数參数的传递原理: 1.函数參数是以栈这样的数据结构来存取的,在函数參数列表中,从右至左依次入栈. 2.參数的内存存放格式:參数的内存地址存放在内存的堆栈段中, ...
- java课堂练习之可变參数与卫条件
/* 有人邀请A,B,C,D,E,F 6个人參加一项会议,这6个人有些奇怪.由于他们有非常多要求,已知: 1)A,B两人至少有1人參加会议: 2)A,E,F 3人中有2人參加会议. 3)B和C ...
- OC可变參数的函数实现va_start、va_end、va_list的使用
一.简单介绍 我们常常在编程的时候看见类似这种代码,如图1.1 图1.1 或者是这种可变參数,如图1.2 图1.2 二.基本知识介绍 在学习怎样写这样的格式的函数前,先简介几个经常使用的宏: 下面摘自 ...
- iOS 处理方法中的可变參数
## iOS 处理方法中的可变參数 近期写了一个自己定义的对话框的demo,想模仿系统的UIAlertView的实现方式.对处理可变參数的时候,遇到了小问题,于是谷歌了一下.写下了处理问题的方法.记录 ...
- Effective JavaScript Item 21 使用apply方法调用函数以传入可变參数列表
本系列作为Effective JavaScript的读书笔记. 以下是一个拥有可变參数列表的方法的典型样例: average(1, 2, 3); // 2 average(1); // 1 avera ...
- java 可变參数
我们在某些特定的需求环境下,可能要对某一个方法中的參数进行一些操作,并且这些方法中的參数是不规定的,那么问题来了,我们该怎么办呢? java事实上就为我们考虑了这样的情况,那就是使用可变參数 可变參数 ...
- java 可变參数列表
Java SE5加入了可变參数列表特性 參数能够这样定义.(Object-args).可变參数用"..."来定义,args是可变參数的数组.举个样例: package sample ...
- java之 ------ 可变參数和卫条件
可变參数:适用于參数个数不确定.类型确定的情况,java把可变參数当做数组处理. 可变參数必须位于最后一项.当可变參数个数多于一个时,必将有一个不是最后一项,所以仅仅支持有一个可变參数. 可变參数的书 ...
- 增强for循环、Map接口遍历、可变參数方法
增强for循环 1.for循环能做得事情.增强for循环大部分都能做(假设要想获得下标的时候就必须使用简单for循环了) 2.增强for有时候可以方便的处理集合遍历的问题,可是集合的标准遍历是使用迭代 ...
随机推荐
- [uiautomator篇] 获取当前页面的方法
Uiautomator 在2.0之前的版本里就提供了getCurrentActivity()的方法,但返回内容不正确:2.0 版本今天尝试了下,还是返回有问题的: 有点没描述清楚啊,是在uiautom ...
- 九度oj题目1008:最短路径问题
题目描述: 给你n个点,m条无向边,每条边都有长度d和花费p,给你起点s终点t,要求输出起点到终点的最短距离及其花费,如果最短距离有多条路线,则输出花费最少的. 输入: ...
- 九度oj 题目1086:最小花费
题目描述: 在某条线路上有N个火车站,有三种距离的路程,L1,L2,L3,对应的价格为C1,C2,C3.其对应关系如下: 距离s 票价 0<S<=L1 ...
- SPOJ GSS6 Can you answer these queries VI ——Splay
[题目分析] 增加了插入和删除. 直接用Splay维护就好辣! 写了一个晚上,(码力不精),最后发现更新写挂了 [代码] #include <cstdio> #include <cs ...
- [BZOJ3611] [Heoi2014]大工程(DP + 虚树)
传送门 $dp[i][0]$表示节点i到子树中的所有点的距离之和 $dp[i][1]$表示节点i到子树中最近距离的点的距离 $dp[i][2]$表示节点i到子树中最远距离的点的距离 建好虚树后dp即可 ...
- [BZOJ1592] [Usaco2008 Feb]Making the Grade 路面修整(DP)
传送门 有个结论,每一个位置修改高度后的数,一定是原来在这个数列中出现过的数 因为最终结果要么不递增要么不递减, 不递增的话, 如果x1 >= x2那么不用动,如果x1 < x2,把x1变 ...
- NOI2015 荷马史诗 【k-哈夫曼树】
题目 追逐影子的人,自己就是影子 --荷马 Allison 最近迷上了文学.她喜欢在一个慵懒的午后,细细地品上一杯卡布奇诺,静静地阅读她爱不释手的<荷马史诗>.但是由<奥德赛> ...
- hihoCoder1381 - Little Y's Tree
Portal Description 给出一个\(n(n\leq10^5)\)个点的带边权的树.进行\(Q\)次询问:每次删除树上的\(k\)条边,求剩下的\(k+1\)个连通块中最远点对距离的和.\ ...
- 【BZOJ3514】Codechef MARCH14 GERALD07加强版(LCT)
题意:N个点M条边的无向图,q次询问保留图中编号在[l,r]的边的时候图中的联通块个数. 询问加密,强制在线 n,m,q<=200000 题意:RYZ作业 以下转载自hzwer http://h ...
- 关于代码调试de那些事
原文出处:http://www.wklken.me/posts/2014/11/23/how-to-debug.html 关于代码调试de那些事 1.你得明白你在做什么, 保持清醒 2.想清楚了再写代 ...