首页 新闻 会员 周边

使用union是出现的奇怪现象

1
[待解决问题]

#include <stdio.h>

union data
{
 int i;
 char ch;
 float f;
};

void main()
{
 data a;
 a.i = 12;
 a.ch = 'd';
 a.f = 3.14;

 printf("%f , %f , %f\n",a.i,a.ch,a.f);

 printf("%f\n",a.i);
 printf("%f\n",a.ch);
 printf("%f\n",a.f);

}

 

大家运行以上代码就会发现困惑的地方,求高手解答!

墨一锭的主页 墨一锭 | 初学一级 | 园豆:200
提问于:2011-10-21 16:24
< >
分享
所有回答(3)
0

估计是VC的BUG。

回去用Apple LLVM3.0试试。

zenny_chen | 园豆:205 (菜鸟二级) | 2011-10-21 18:04

Apple LLVM3.0的结果是:

3.140000 , 5346770821002303130567579097432459885478841752405191249081923787099425423943170000977628845339275495171402680361067749291112378768335284427858254517505621456702285766243904170591855470977966440666493824281116226233501341458628608.000000 , 0.000000

3.140000

3.140000

3.140000

支持(0) 反对(0) zenny_chen | 园豆:205 (菜鸟二级) | 2011-10-22 00:54

楼主这边要注意的是printf函数在解析不定参数的时候是根据format字符串里的类型信息来确定参数类型的。比如说,这里第一个出现的是%f,这是一个定点的双精度类型,因此对于第一个参数,它会取四个字节;而解析到第二个%f后,printf认为第二个参数仍然要取四个字节,但实际上,ch只给了一个字节,因此这会与存储器后面的内容产生叠交。而在取第三个参数的时候,由于之前取第二个参数的时候跨了四个字节,所以第三个参数的内容没有正确地取得,结果为0.0000。

支持(0) 反对(0) zenny_chen | 园豆:205 (菜鸟二级) | 2011-10-22 01:13
0

你这个代码本身就是不正确的吧

union里面存了一个float,int,char,这三个共享同一块内存,但是有谁告诉你,这三个东西的起始地址都是一样的???

int么,你碰到了个狗屎,因为32bit的机器下面,int大部分都是32bit,跟float刚好一样,所以int拿float格式化,有可能是正确的.

char的话,god know.

egmkang | 园豆:-734 (初学一级) | 2011-10-24 15:32
0

printf("%f , %f , %f\n",a.i,a.ch,a.f);

问题出在你这句话上,printf是可变参数函数,这种函数在push参数的时候,计算参数的size是根据后面的参数列表的实际类型。而打印的时候又是按照前面的“%f, %f, %f"来的。所以它取参数的时候是按照一个一个float数据占据的大小来到栈上去的。而你push参数的时候压入的字节数却分别是float,char,int之类的,这就导致在printf里面取参数的时候出现错位。

printf("%f\n",a.ch); 这种调用也是有问题的,如果打印出来正确,那可能是偶然的现象,例如或者栈上保留的上一次调用的残留数据恰好未被覆盖过,但正常时不可以这样使用。

hoodlum1980 | 园豆:559 (小虾三级) | 2012-06-07 17:06
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册