鱼C论坛

 找回密码
 立即注册
查看: 2961|回复: 0

[技术交流] 大端小端区别、Union和Struct的内存分配

[复制链接]
发表于 2011-10-26 14:59:28 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
嵌入式系统开发者应该对Little-endian和Big-endian模式非常了解。采用Little-endian模式的CPU对操作数的存放方式是从低字节到高字节,而Big-endian模式对操作数的存放方式是从高字节到低字节。也就是说Big-endian模式符合人的习惯,而Little-endian更加方便计算机操作。
例如,16bit宽的数0x1234在Little-endian模式CPU内存中的存放方式(假设从地址0x4000开始存放)为:
内存地址 0x4000 0x4001
存放内容 0x34 0x12
而在Big-endian模式CPU内存中的存放方式则为:
内存地址 0x4000 0x4001
存放内容 0x12 0x34
32bit宽的数0x12345678在Little-endian模式CPU内存中的存放方式(假设从地址0x4000开始存放)为:
内存地址 0x4000 0x4001 0x4002 0x4003
存放内容 0x78 0x56 0x34 0x12
而在Big-endian模式CPU内存中的存放方式则为:
内存地址 0x4000 0x4001 0x4002 0x4003
存放内容 0x12 0x34 0x56 0x78
若判断处理器是Big还是Little模式,有两种方法。
1、
int i=1;   
    char *p=(char *)&i;   
    if(*p==1)     
           printf("1");  
    else
           printf("2");
          大小端存储问题,如果小端方式(i占至少两个字节的长度)则i所分配的内存最小地址那个字节中就存着1,其他字节是0.大端的话则1在i的最高地址字节处存放,char是一个字节,所以强制将char型量p指向i则p指向的一定是i的最低地址,那么就可以判断p中的值是不是1来确定是不是小端
2、
int checkCPU( )
{
    {
           union w
           {  
                  int a;
                  char b;
           } c;
           c.a = 1;
           return(c.b ==1);
    }
}
这个解法涉及到Union的内存分配模式。
Union的大小为其内部所有变量的最大值,并且按照类型最大值的整数倍进行内存对齐。
例如:
typedef Union
{
char c[10];
char cc1;
}u11;首先按照char c[10]分配10个字节,然后按照char的1个字节对齐,最终sizeof(u11)=10;
typedef union
{
char c[10];
int i;
}u22;首先按照char c[10]分配10个字节,然后按照int的4个字节对齐,最终sizeof(u22)=12;
typedef union
{
char c[10];
double d;
}u33;首先按照char c[10]分配10个字节,然后按照double的4个自己对齐,最终sizeof=16;
union U1  {
5  char  c;
6  int  i;
7  double  d;
8     } ;按照double的8个字节分配,最终为8;
9  union U2  {
10  char  c;
13      } ;按照char c的一个字节分配,最终sizeof为1;
14
15  union U3  {
16  char  c;
17  int  i;
18  // double d;
19      } ;按照int的4个字节分配,最终sizeof为4;
因此,举例中union分配的内存按照int分配4个字节,如果是小端模式则存放的方式为                                                                                                      
地址A
------------------------------------
|A       |A+1   |A+2    |A+3 | int a;
|0x01 |0x00   |0x00   |0x00 |
-------------------------------------
|A      |char b;
|          |
---------         
如果是大端如何存储c.a的呢?   
地址A
------------------------------------------
|A          |A+1    |A+2      |A+3      |int a;
|0x00   |0x00   |0x00    |0x01    |
------------------------------------------
|A       |char b;
|            |
---------      
因此我们就可以通过查看char b==1?来判断大小端了。
顺便说明一下struct的内存分配方式。
struct的内存大小为每个数据内存的加和,首先按照最大的数据类型进行单个分配,如果前一个数据占用不了所有的内存,而剩下的内存可以放下下一个数据,则第二个数据不另外分配内存,否则重新分配一个最大类型的内存单元。
struct{
char c;
double d;
};16
struct{
char c;
char c1;
double d;
};16
struct{
char c;
double d;
char c2;
};24
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-10-8 19:49

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表