參考文档: http://bbs.csdn.net/topics/70288067

Owed by: 春夜喜雨 http://blog.csdn.net/chunyexiyu 转载请标明来源

本文的二个重点:

1. 可变參数实际上通过首个參数的地址来获取其他參数的地址。由于是顺序存储传过来的

1.      可变參数为了处理方便。全部的浮点型都是依照double型压栈。

因此,像printf採用的可变參数,它直接使用%f显示double型。不须要管float型。

关注printf的精度,须要先关注printf的实现,关于printf的实现,我们就要关注一下可变參数的实现:

变參的一个例了:

void
testIntAndFloat(int
type, ...)

{

va_list argptr;

va_start(argptr,
type);

if (type == 0 )

{

int n = va_arg(
argptr, int );

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

}

else if (type == 1)

{

double d =
va_arg( argptr,
double); // 必须使用double接收,后边会说明原因

printf( "%f\n",
d);

}

else

{}

}

測试:

float
f1 = 12345;

testIntAndFloat(0,
);

testIntAndFloat(1,
f1, f1);

输出:

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
i = 123456;

printf("%d,%d \n",i,
i);

结果为: 123456, 0

printf("%d,%d,%d,%d \n",i,
i);

结果为: 123456,0,123456,0

printf("%lld,%lld \n",i,
i);

结果为: 123456, 123456

从上面的内容能够看出来:

%d时,每次读取的位数是4位,而int64有8位。所以假设使用%d的话,分两次读取完。

(因为是little endian。先读低位,再读高位,先读到123456。再读到0)

再看输出%f的样例

float
f = 123456789123456789.0;

double fd = f;

double
d = 123456789123456789.0;

printf("%f\%f\n%f\n",f,fd,
d);

结果为:

1234567939550609400.0000

1234567939550609400.0000

1234567890123456800.0000

能够看出:

float实际是被转成double型存储显示的

(float的精底一般是6-7位。double是15-16位,printf的时候,显示的位数是按double算的。)

再看这个样例,执行时观察内存信息:

(观察内存方式: VC->调试->窗体->内存)

void
testArgs(int
type, ...)

{

va_list argptr;

va_start(argptr,
type);

for (int i=0;
i<8; i++)

{

int* pNumber = (int*)argptr;

float* pFloat = (float*)argptr;

va_arg(argptr,
int);

printf(("\naddrss:%d int value: %d  float value: %f"),
pNumber, *pNumber, *pFloat);

}

}

void
TestFuncArgs(int
n1 = 31, float
f1=31.0, double
d1=31.0, char
c1=31, bool b1=31,
short s1=31,
__int64 n2=31,
int n3=31)

{

printf("\nf1=%f",
f1);

printf(("\naddrss of arg(int): %x, value: %d"), &n1,
n1);

printf(("\naddrss of arg(float): %x, value: %d|%d, float:%f"), &f1,
f1, f1);

printf(("\naddrss of arg(double): %x, value: %d|%d, float:%f"), &d1,
d1, d1);

printf(("\naddrss of arg(char): %x, value: %d"), &c1,
c1);

printf(("\naddrss of arg(bool): %x, value: %d"), &b1,
b1);

printf(("\naddrss of arg(short): %x, value: %d"), &s1,
s1);

printf(("\naddrss of arg(__int64): %x, value: %d"), &n2,
n2);

printf(("\naddrss of arg(int): %x, value: %d"), &n3,
n3);

testArgs(n1,
f1, d1, c1,
b1, s1,
n2, n3);

}

当按函数定參參数形式传递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

1f 00 00 00--double 
 
Owed by: 春夜喜雨 http://blog.csdn.net/chunyexiyu 转载请标明来源
 

Printf可变參数使用的更多相关文章

  1. C语言利用va_list、va_start、va_end、va_arg宏定义可变參数的函数

    在定义可变參数的函数之前,先来理解一下函数參数的传递原理: 1.函数參数是以栈这样的数据结构来存取的,在函数參数列表中,从右至左依次入栈. 2.參数的内存存放格式:參数的内存地址存放在内存的堆栈段中, ...

  2. java课堂练习之可变參数与卫条件

    /*  有人邀请A,B,C,D,E,F 6个人參加一项会议,这6个人有些奇怪.由于他们有非常多要求,已知:  1)A,B两人至少有1人參加会议:  2)A,E,F 3人中有2人參加会议.  3)B和C ...

  3. OC可变參数的函数实现va_start、va_end、va_list的使用

    一.简单介绍 我们常常在编程的时候看见类似这种代码,如图1.1 图1.1 或者是这种可变參数,如图1.2 图1.2 二.基本知识介绍 在学习怎样写这样的格式的函数前,先简介几个经常使用的宏: 下面摘自 ...

  4. iOS 处理方法中的可变參数

    ## iOS 处理方法中的可变參数 近期写了一个自己定义的对话框的demo,想模仿系统的UIAlertView的实现方式.对处理可变參数的时候,遇到了小问题,于是谷歌了一下.写下了处理问题的方法.记录 ...

  5. Effective JavaScript Item 21 使用apply方法调用函数以传入可变參数列表

    本系列作为Effective JavaScript的读书笔记. 以下是一个拥有可变參数列表的方法的典型样例: average(1, 2, 3); // 2 average(1); // 1 avera ...

  6. java 可变參数

    我们在某些特定的需求环境下,可能要对某一个方法中的參数进行一些操作,并且这些方法中的參数是不规定的,那么问题来了,我们该怎么办呢? java事实上就为我们考虑了这样的情况,那就是使用可变參数 可变參数 ...

  7. java 可变參数列表

    Java SE5加入了可变參数列表特性 參数能够这样定义.(Object-args).可变參数用"..."来定义,args是可变參数的数组.举个样例: package sample ...

  8. java之 ------ 可变參数和卫条件

    可变參数:适用于參数个数不确定.类型确定的情况,java把可变參数当做数组处理. 可变參数必须位于最后一项.当可变參数个数多于一个时,必将有一个不是最后一项,所以仅仅支持有一个可变參数. 可变參数的书 ...

  9. 增强for循环、Map接口遍历、可变參数方法

    增强for循环 1.for循环能做得事情.增强for循环大部分都能做(假设要想获得下标的时候就必须使用简单for循环了) 2.增强for有时候可以方便的处理集合遍历的问题,可是集合的标准遍历是使用迭代 ...

随机推荐

  1. Playrix Codescapes Cup (Codeforces Round #413, rated, Div. 1 + Div. 2) D. Field expansion

    D. Field expansion time limit per test 1 second memory limit per test 256 megabytes input standard i ...

  2. 机房合作(三):We are Team,We are Family

    导读:拖拖拉拉,机房的合作也算是接近了尾声了.在这个过程中,真心是感谢我的两个组员.这个机房合作,看似简单,但我的组员给我的帮助和感动,都是不可忽略的.记得刚开始的时候,我就说过:不怕猪一样的组长,咱 ...

  3. 【Kubernetes】深入解析声明式API

    在Kubernetes中,一个API对象在Etcd里的完整资源路径,是由:Group(API组).Version(API版本)和Resource(API资源类型)三个部分组成的. 通过这样的结构,整个 ...

  4. 只操作git(cmd)就可以使用git将项目上传到github

    代码改变世界 使用git将项目上传到github(最简单方法) 首先你需要一个github账号,所有还没有的话先去注册吧! https://github.com/ 我们使用git需要先安装git工具, ...

  5. C/C++ 命令行参数的实现方法

    解析从命令行提供的参数可以使用 getopt函数. To use this facility, your program must include the header file unistd.h u ...

  6. 【leetcode dp】Dungeon Game

    https://leetcode.com/problems/dungeon-game/description/ [题意] 给定m*n的地牢,王子初始位置在左上角,公主在右下角不动,王子要去救公主,每步 ...

  7. NAND FLASH 物理结构分析

    转自:http://blog.51cto.com/hardywang/2053915 NAND Flash是一种非易失性随机访问存储介质,基于浮栅(Floating Gate)晶体管设计,通过浮栅来锁 ...

  8. 《写给大忙人看的Java核心技术》 勘误

    先附上十分讨喜的封面.这应该是爱丽丝梦游仙境里的那只兔子吧? 勘误表基于原版勘误表制作 链接 截止日期 2017-02-09 对应<写给大忙人看的Java核心技术>2016年1月第1次印刷 ...

  9. 【Vijos1250】最勇敢的机器人(并查集,分组背包DP)

    题意:有N个物品,承重上限为M,有K组物品互斥关系,互斥关系有传递性,即1与2互斥,2与3互斥,1与3也互斥 给出每个物品的花费和价值,求承重上限内的最大价值总和 n<=1000,m<=1 ...

  10. net3:Button的CommandName使用,AdRotator,BulletedList的使用

    原文发布时间为:2008-07-29 -- 来源于本人的百度文章 [由搬家工具导入] using System;using System.Data;using System.Configuration ...