求高人解释一下

gz_qmc 2014-01-05 06:13:07
代码:
int main(int argc, char* argv[])
{
float a=1.2,b=0.01;

printf("%08X\n\n%08X\n\n",b,a);

printf(" \n");

printf("%08X\n\n%08X\n\n",a,b);

return 0;
}


结果:

...全文
287 点赞 收藏 25
写回复
25 条回复
寒沙胜雪 2014年03月03日
c primer plus上面说得很清楚,从右向左压栈之后按照类型说明符读取数据。
回复 点赞
坏坏62 2014年01月06日
难道不是应该”%f\n“对应单精度数???
回复 点赞
gz_qmc 2014年01月05日
结合6楼和13楼,我基本弄明白了其中道理 晕死!结帐
回复 点赞
vipcxj 2014年01月05日
http://www.cnblogs.com/elitegoblin/archive/2013/06/07/3123964.html LZ可以看看这篇帖子的最后一段,简单说来就是对于一般的函数,参数都是有明确类型声明的,那么传进去的参数都会按照参数声明的转换,但对于printf,他后面的参数的类型是不定的,所以编译器的做法就是对你所传入的参数先进行类型提升后再传入函数。具体说来就是char,short,int都变成int,float,double都变成double,这也是为什么%f能同时处理float和double的原因,因为传进去的参数都会自动变成double
回复 点赞
Pump天天学习 2014年01月05日
printf("%08X\n\n%08X\n\n",b,a); 在这个printf里,第一个%x取到变量b的低地址4个字节(因为按int取),第二个%x取到b的后面的四个字节, 这时就结束了,和变量a没有任何关系
回复 点赞
baichi4141 2014年01月05日
printf的可变参数列表用第一个字符串的内容去解析栈中的数据 因为float自动转换成double,因此两个%X总共解析的8字节的栈顶数据,实际上属于一个double变量 因为是从右向左压栈,所以printf("%08X\n\n%08X\n\n",b,a);和printf("%08X\n\n%08X\n\n",b);是一样的,反之同理
回复 点赞
Pump天天学习 2014年01月05日
引用 10 楼 gz_qmc 的回复:
[quote=引用 8 楼 CKnightx 的回复:] 我以为只是简单的数据截断,没想到跟printf还拉上关系了。 抱歉,哥,我也涨点见识。
无关紧要,一起思考,我估计是不是printf本身就有问题 [/quote] 写这些函数的那帮人不会让我们这种等级的人抓住把柄的
回复 点赞
Pump天天学习 2014年01月05日
引用 9 楼 gz_qmc 的回复:
6楼的道理还是说服不了我 就算float压栈的时候转换成double 因为任何一个变量,我不管你怎么储存 我取a值的动作,a所指向的内存位置怎么能变呢? 就算你printf("...",a,a) 有出栈的顺序导致得到两个地址 但printf("...",a,b) 和printf("...",b,a) a和b各自只取一次怎么会变呢
这说明鸟哥你根本没用认真看我给的链接 你的程序输出的根本就不是a,b变量的值 测试一下这个代码,看看和你的一样不

#include <stdio.h>

int main(int argc, char* argv[])
{
	float a=1.2,b=0.01;

	printf("%08X\n\n%08X\n\n",b);//注意:这里输出的只有b

        printf("    \n");        

	printf("%08X\n\n%08X\n\n",a);//这里只有a

	return 0;
}
回复 点赞
lm_whales 2014年01月05日
勘个误,两个程序里应该是两个输出语句里 你可以这样看看
int main(int argc, char* argv[])
{
    float a=1.2,b=0.01;
    double da = a,db = b;
    int *pa =(int * )&da; 

    printf("%08X\n\n%08X\n\n",b,a);
 
        printf("    \n");        
    printf("%08X\n\n%08X\n\n",b,a);
     
    后面的输出,跟前面两个相同,或者反序(如果有字节序问题)
    printf("%08X\n\n%08X\n\n%08X\n\n%08X\n\n",pa[0],pa[1],pb[0],pb[1]);

    return 0;
}
回复 点赞
CoolEgos 2014年01月05日
好像很深奥的样子,受用了
回复 点赞
一入程序深似海 2014年01月05日
引用 12 楼 CKnightx 的回复:
[quote=引用 10 楼 gz_qmc 的回复:] [quote=引用 8 楼 CKnightx 的回复:] 我以为只是简单的数据截断,没想到跟printf还拉上关系了。 抱歉,哥,我也涨点见识。
无关紧要,一起思考,我估计是不是printf本身就有问题 [/quote] 每一次运行,都是同样的结果吗?还是地址都是变化的? 函数参数传递的时候,因为传递的是值,只是简单把值复制过去了。 也就是说,在printf函数内部,a和b的存储位置,都是新的(临时变量)地址。 [/quote] 也不对,printf变参函数,在访问argv时候,都是地址访问的。不会开辟新的空间。 等高人给权威回复吧
回复 点赞
lm_whales 2014年01月05日
C调用约定,多余的参数会丢弃。 float ,double,参数传递的长度是double的长度。 char,short,int 参数传递的长度是int的长度。 printf 函数第一个为格式串,余下的参数按照格式的需要匹配 %x 格式按照 int类型和参数匹配,即匹配sizeof(int) 的长度; 即16位程序2字节,或者32位程序4字节。 两个程序里,第二个参数是多余参数,不会出错,但是不起作用。
回复 点赞
一入程序深似海 2014年01月05日
引用 10 楼 gz_qmc 的回复:
[quote=引用 8 楼 CKnightx 的回复:] 我以为只是简单的数据截断,没想到跟printf还拉上关系了。 抱歉,哥,我也涨点见识。
无关紧要,一起思考,我估计是不是printf本身就有问题 [/quote] 每一次运行,都是同样的结果吗?还是地址都是变化的? 函数参数传递的时候,因为传递的是值,只是简单把值复制过去了。 也就是说,在printf函数内部,a和b的存储位置,都是新的(临时变量)地址。
回复 点赞
lm_whales 2014年01月05日
引用 4 楼 gz_qmc 的回复:
不管%x对不对应整数 对于a和b来说 所存储的2进制数肯定是一定的 为什么显示a,b和显示b,a 结果两次显示结果a和b都对不上呢?
第一个显示了a,第二个显示b 两个都是对的,不过你的程序这样编写是错误的。
回复 点赞
gz_qmc 2014年01月05日
引用 8 楼 CKnightx 的回复:
我以为只是简单的数据截断,没想到跟printf还拉上关系了。 抱歉,哥,我也涨点见识。
无关紧要,一起思考,我估计是不是printf本身就有问题
回复 点赞
gz_qmc 2014年01月05日
6楼的道理还是说服不了我 就算float压栈的时候转换成double 因为任何一个变量,我不管你怎么储存 我取a值的动作,a所指向的内存位置怎么能变呢? 就算你printf("...",a,a) 有出栈的顺序导致得到两个地址 但printf("...",a,b) 和printf("...",b,a) a和b各自只取一次怎么会变呢
回复 点赞
一入程序深似海 2014年01月05日
我以为只是简单的数据截断,没想到跟printf还拉上关系了。 抱歉,哥,我也涨点见识。
回复 点赞
一入程序深似海 2014年01月05日
我擦,我看错题目了。
回复 点赞
Pump天天学习 2014年01月05日
printf是以压栈的形式处理参数的,并且把它压进去的时候float转换成double 看这里的1,2,3,5楼,,解释的很详细,说简单了就是把double截断了 贴个测试代码,但是与lz的问题相似

int main(int argc, char* argv[])
{
	float a=125.5;
	printf("%x %x\n",a,a);//这里打印出来的两个a值也不相同
	printf("%x\n",a);//下面两行却相同
	printf("%x",a);
	return 0;
}
回复 点赞
一入程序深似海 2014年01月05日
哥,建议你先去看看《深入理解计算机系统》的前几章。 里面讲述了浮点数是如何存储的。 要用计算机的思维去写程序。
回复 点赞
发动态
发帖子
C++ 语言
创建于2007-09-28

3.1w+

社区成员

24.8w+

社区内容

C++ 语言相关问题讨论,技术干货分享
社区公告
暂无公告