关于c语言共用体的问题
你好!!!
首先我们了解联合体的所有成员是在内存中共享一块内存的,在某一时刻只能有一个成员使用这个内存!!!
我们来看看一个例子:
#include
union
{
int i;
char x[2];
}a;
void main()
{
a.x[0] = 10;
a.x[1] = 1;
printf("%d",a.i);
}
答案:266
解释如下:
union
{
int i;
char x[2];
}a;
在联合体a中定义了两种数据类型,字符数组x以及整形变量i.其中整形变量是16位的,数组大小为2的字符数组为8X2=16位。如此一来,编译器便会为联合体a在内存中开辟一个16位的空间,这个空间里存储联合体的数据,但是这个空间只有16位,它既是整形变量的数据,也是字符数组的数据。如果你的程序从字符数组的角度解析这个空间,那么它就是两个字符,如果你的程序从整型的角度解析这个空间,那么它就是一个整数。
以你的程序为例子,现在已经开辟了一个16位的空间,然后我们假定现在空间还没有被赋值,为:
00000000 00000000
那么在运行完代码
a.x[0] = 10;
a.x[1] = 1;
之后,16位的空间变为:
00001010 00000001
然后程序运行
printf("%d",a.i);
就是把联合体a当成一个整数来解析,而不是字符串数组。那么这样一来,程序就把这16位变成了一个完整的整数:
(00000001 00001010)二进制 = (266)十进制
注意,你可以看到程序在把16位弄成整数的时候把后面八位放在了前面,前面八位放在了后面。这个反序是计算机存储结构造成的,这个和联合体没有直接关系。如果感兴趣的话可以参考汇编语言。
现在我们来看看,你给的例子:
union dt
{
int a;
char b;
double c;
}data;
此时的联合体所占的内存大小是8个字节,接下来执行:
data.a=5;
此此时内存中就不是空的了,也就不会是你说的是随机数,
但是输出:printf("%lf",data.c);结果是0.000000,这个结果我还不能给你准确的解释。但是我可以肯定这与系统把double转换成int 和int 转化成 double 有关!!!
暂时我只能解释这那多!!!
这个是共用体的问题
由于共用体共用同一段起始内存的地址,所以后一次的数据写入可能会覆盖前一次的数据
然后lz这道题,如果系统将int做2直接处理(比如TC2)的话,结果是380039和9;如果是按4字节处理的话,结果应该是39和9
下面针对lz的结果,讲一下2字节处理的情况
第一个共用体成员是int的数组,两个元素,共4字节
第二个成员是long,4字节
第三个成员是char数组,4个元素,4字节
所以这个union变量共4字节
s.a[0]=0x39;
s.a[1]=0x38;
导致变量s的内存存储的16进制数据(小尾存储的话)高位到低位依次为为
00 38 00 39
所以才会导致输出380039和9
4字节处理的话,同理
int型的变量 占2个字节,而一个内存单元只有一个字节的大小,因此int型变量要分开放。
那怎么放呢?是这样的,先把int变量分成两个字节,前八位作为高字节,后八位作为低字节,这样,把高字节的那八位放在低地址内存单元,低字节的那八位放在高地址内存单元。
而long型的占四个字节,也是一样的,分成四个字节分开放,高字节放低地址内存单元。
你的程序中,只占一个字节的0x39给了int型的i[0],那这样,高字节为0,假设放在最低地址的内存单元中,那0x39就顺着往上放,i[1]也一样。好了,这样放完后,这个占四个字节的共用体变量的存储情况就是:0x38 / 0x00 / 0x39 / 0x00 (说明:左手边为高地址,右手边为低地址)。
i[1] i[0]
好了,我们现在是取long型的k,那很显然,低地址的存储单元是它的高字节,高地址的存储单元是它的低字节,这样就得到:0x 00 39 00 38 。
这是我用keil-C51仿真得到的结果,如果你问为什么结果跟你的不一样,那我只能回答:系统决定变量的存放方式。
共同体(联合体)的特点是所有成员变量共享同一块内存单元。
另外
(1)当各成员长度不相等 时,内存块的大小由 最长的决定。-- 你的几个成员长度相等,无此问题。
(2)数据存放时涉及字节次序,分大端序和小端序。WINDOWS 用小端序。
小端序:
i[2] 的 排列 是 i[0] 2字节,i[1] 下面的2字节
i[0] 里2个字节 低字节在前,高字节在后 0x0039 排列成 0x39 0x00
i[1] 里2个字节 低字节在前,高字节在后 0x0038 排列成 0x38 0x00
于是4个字节内容 是 0x39 0x00 0x38 0x00
翻译成 long int k:
k 的4字节 排列 是:最低字节,低字节,高字节,最高字节 (0x39 0x00 0x38 0x00)
输出数据时要拼成:最高字节 高字节 低字节 最低字节 也就是 0x00 0x38 0x00 0x39
输出为 0x00380039 (输出格式 0x%08x)
或 380039 (输出格式 %x)
大端序从略。
共用体是构造数据类型,也叫联合体
它使几个不同类型的变量共占一段内存(相互覆盖),每次只有一个能使用.
结构体则不然, 每个成员都会有存储空间的,可以一起用.
32位操作系统下 short int占2字节,int占4字节,38=1个字节, 00=2个字节,39=1个字节;
为什么先输出38然后39呢,因为数据储存在遵循了 先进后出原则,这涉及到共用体类型数据的存储。这里不能长篇大论了。
所以呢,s->k读取的是 数组i[2]地址的数据
度娘不知道哪里抽了
16进制39,38化成二进制就是111001和111000
因为short int 2字节就是16位,所以两个都要在前面补0,每个都要够16位
得到0000000000111001和0000000000111000
连起来就是00000000001110010000000000111000
然后你会发现这就是16进制的380039
C语言共用体的问题
to楼上同学,首先,全局数据区的变量一般可以认为会被初始化为全0,另外,你认为scanf("%d%d",&u.i[0],&u.i[1]);语句是在干什么?to楼主:一个小问题,你的环境中int和long的字长是多少?似乎int是16bit,long是32bit?实际上这个问题最烦的是float,其他的都简单,而人工分析float的输出值...
C语言共同体的问题 union dt{int a;char b;double c;}data;
(1)共同体在内存中共用一块存储空间,(2)空间的大小由共同体中占用空间最大的变量所决定 (3)输出时,按相应的类型进行数值解析。int 占4个字节 char 占一个字节 double占8个字节 所以data所占空间为8字节。data.a=5;在内存中存储的是二进制格式,X86机器上,低位在前形如:00000101 ...
c语言共用体的问题
您好,chang.a=16961; 在内存中存储的值对应的十六进制是:4241 由于是a处于联合中,所以char c[2];的起式地址跟chang.a是相同的。在根据在内存中存储的高=低位关系,就很容易理解了。chang.c[0] 对应的地址就是 41 所在的内存地址,chang.c[1]对应的就是42 对应的内存地址。经过printf输出,...
c语言共用体输出问题
这个是共用体的问题 由于共用体共用同一段起始内存的地址,所以后一次的数据写入可能会覆盖前一次的数据 然后lz这道题,如果系统将int做2直接处理(比如TC2)的话,结果是380039和9;如果是按4字节处理的话,结果应该是39和9 下面针对lz的结果,讲一下2字节处理的情况 第一个共用体成员是int的数组,...
c语言共用体问题
关键你需要知道变量在内存中的排列 10为 0000 1010 1 为 0000 0001 拼在一起:0000 0000 0000 0000 0000 0001 0000 1010 就是 266
关于C语言 共用体(联合体) 元素覆盖问题
共用体内的数据在内存的起始地址是相同的,长度与最大的类型相同。你的程序,虽然第一次赋值r[0]=2,但是r[0]的地址和k的地址相同,所以k=20这个语句执行后r[0]也等于20了。
C语言中共用体问题
其实不然,首先你要理解共用体的含义,它不是表示共用体能够同时放入三个不同类系的数据。共用体实际上只有一个存储单位,在每一个瞬间只有一个类型的数据被存入里面,也就是它才起作用,你这里把data.a=5,说明共用体中整形数被赋值,这里的data.b,data.c就不存在了,所以只能正常的输出a的值,...
c语言共用体问题
选择c:公用体所占的内存的长度是其成员类型的最大长度,此内存某一时刻只能存放一种数据,结构体内可以有公用体,公用体内也可以有结构体。
关于一个C语言共用体赋值问题
教科书说的理论上是没有错的,因为联合体中各变量是共用内存的,一个联合变量的长度等于各成员中最长的长度,联合变量可被赋予任一成员值,但每次只能赋一种值, 赋入新值则冲去旧值。http:\/\/hi.baidu.com\/hsyl\/blog\/item\/3a9af91900a43376dbb4bdf0.html\/cmtid\/94dc8b82ebba7a9ff703a6f2 出...
关于C语言共用体的问题谢谢
dat已赋值,c没有赋值,但它们存在于同一公用体里,所以c的值是由dat的三个值决定。内存中存储的是二进制,所以应该将dat的三个值转换为二进制,然后每8Bit为c的一个字符的值,所以可能出现负数 你可以将打印那句改成printf("%d\\n",uni.c[i]);以便观察c的每一个值 ...