先看一个示例:

// C code: bit fields & CPU endian
#include <stdio.h>struct bit_field{unsigned short bit4:4;unsigned short bit3:3;unsigned short bit2:2;unsigned short bit7:7;
};int main()
{struct bit_field bit;bit.bit4=10;bit.bit3=5;bit.bit2=1;bit.bit7=8;printf("%x\r\n", *(unsigned short *)&bit);return 0;
}

在big-endian机器上的结果是aa88
1010,101,01,0001000 (10 5 1 8)
1010,1010,1000,1000 ( A  A 8 8)

在small-endian机器上的结果是10da
0001000,01,101,1010 (8 1 5 10)
0001,0000,1101,1010 (1 0 D  A )

位域操作在不同系统中有两处是不同的
1 编译器编译结果是不同的
        因为CPU对于存储器不能进行位操作,每次读写的最小单位是字节,所以每次位域赋值操作编译器都要将位域的值转换为一个或多个字节长度的数值,将这个数值与存储器中原有的值进行或操作;配置了不同CPU类型的编译器对于相同的位域转换成的数值是不一样的,对于配置CPU类型为MPC8260的,gcc编译器它将结构中先声明的位域做为该位域所属结构元素的高位,后声明的位域做为结构元素的低位,而VC编译器正相反,它将先声明的位域做为结构元素的低位,后声明的位域做为结构元素的高位,为了便于理解可以认为编译器先将结构元素中的各个位域组成一个数值,这个数值的字长等于结构元素的字长,然后通过寄存器将该数值写入存储器中,配置CPU类型为MPC8260的gcc编译器将先声明的位域做为数值高位,而VC编译器将后声明的位域做为高位。因此对于struct bit_field这个结构元素,gcc编译器认为它的值是0xaa88,而VC编译器认为它的值是0x10da。

2 CPU将寄存器的值写入存储器时字节排序是不同的
       因为MCP8260是big-endian模式,运行VC的PC机CPU是Intel系列的采用little-endian模式,所以MPC8260将寄存器内容写入存储器时,将高位字节0xaa写入低地址,将低位字节0x88写入高地址。Intel的CPU正相反,它将高位字节0x10写入高地址,将低位字节0xda写入低地址。位域赋值语句要经过编译过程和执行过程才会转换成存储器中的数值,位域转换到数值的过程发生在编译阶段,将转换后的数值通过寄存器写入存储器之间的操作发生在代码的执行阶段,前者因为编译器不同位域转换成的值也不同,后者因为CPU类型不同而存在着little-endian和big-endian的差异

总结:
       在存储顺序问题上,位域操作有其独特之处,它的存储顺序是CPU和编译器双重作用的结果,CPU决定字节的存储顺序,编译器决定位域的存储顺序。

VC调试时按Alt+8,TC或BC用TD调试,打开汇编窗口看每句C对应的汇编就啥都明白了。(Linux或Unix下应该也可以在用GDB调试时,看每句C对应的汇编。)

link for bit feild basic:

http://blog.sina.com.cn/s/blog_3d8529400100istl.html

http://msdn.microsoft.com/zh-cn/library/yszfawxh.aspx

Here are two usefull code for getting CPU endian type and code for declarator in bit field definition.

//C code: get CPU big endian or small endian
#include <stdio.h>union TEST{unsigned char aa[4];unsigned int  bb;
};int main()
{union TEST test;test.aa[0] = 0x01;test.aa[1] = 0x02;test.aa[2] = 0x03;test.aa[3] = 0x04;if (test.bb == 0x01020304)printf("it's big endiam!\r\n");else if (test.bb == 0x04030201)printf("it's small endiam!\r\n");elseprintf("unknow endiam system! 0x1234 VS 0x%x\r\n", test.bb);return 0;
}
// C code: sizeof bit operation
#include <stdio.h>struct TEST1{unsigned short bit4:4;unsigned short bit3:3;unsigned short bit2:2;unsigned short bit7:7;
};
struct TEST2{unsigned short bit4:4;unsigned short bit3:3;unsigned short bit2:2;unsigned short bit7:7;double bb;
};
struct TEST3{unsigned int bit4:4;unsigned int bit3:3;unsigned int bit2:2;unsigned int bit7:7;
};
struct TEST4{unsigned int bit4:4;unsigned int bit3:3;unsigned int bit2:2;unsigned int bit7:7;double bb;
};int main()
{printf("%d, %d; %d, %d; %d\r\n", sizeof(TEST1), sizeof(TEST2),sizeof(TEST3), sizeof(TEST4), sizeof(double));return 0;
}

result: 2, 16; 4, 16; 8

bit feild and CPU endian 位域和大小端相关推荐

  1. C中的位域与大小端问题

    C中的位域与大小端问题 字节内也是有大小端问题,与字节中的大小端类似: 1)little endian中的位应该这样排列:  01234567  即排在前面的是低位.因此,先分配least signi ...

  2. CPU大小端模式对C语言底层开发的影响

    CPU大小端模式对C语言底层开发的影响 ​ 在嵌入式的c语言底层开发过程中,经常会遇到CPU大小端模式的问题,对底层软件的数据结构构建.数据解析.甚至功能实现上均有一定的影响,我自己在ECU的底层软件 ...

  3. 位域 内存 字节序_C语言中的位域、字节序、比特序、大小端(转)

    1.比特序 / 位序 / bit numbering / 我们知道一个字节有8位,也就是8个比特位.从第0位到第7位共8位.比特序就是用来描述比特位在字节中的存放顺序的.通过阅读网页的内容,关于比特序 ...

  4. C++随记总结(1)----关于C++中的大小端、位段(惑位域)和内存对齐

    C++随记总结(1)----关于C++中的大小端.位段(惑位域)和内存对齐 声明:欢迎任何人和组织转载本blog中文章,但必须标记文章原始链接和作者信息. 本文链接:http://www.cnblog ...

  5. 关于C++ 中大小端和位域

    关于C++中的大小端.位段(惑位域)和内存对齐 听到好几个朋友说到去一些公司做面试,总是遇到关于大小端.位段(或者叫位域)和内存对齐的考题,然后就不知所措了.虽然我认为很多开发根本就用不到这个,但是我 ...

  6. C语言程序判断计算机的CPU大小端

    如何判断一台计算机的CPU是大端还是小字端对齐呢? 那么首先得了解何为大端,何为小端,明确一下概念. 所谓大端模式,是指字数据的高字节存储在低地址中,而字数据的低字节则存放在高地址中. 小端格式:与大 ...

  7. 关于大小端、位域的一些概念

    大小端: 对于像C++中的char这样的数据类型,它本身就是占用一个字节的大小,不会产生什么问题.但是当数制类型为int,在32bit的系统中,它需要占用4个字节(32bit),这个时候就会产生这4个 ...

  8. 关于大小端、位域的一些概念详解

    关于大小端.位域的一些概念详解 我们常用的x86结构都是小端模式,而大部分DSP,ARM也是小端模式,不过有些ARM是可以选择大小端模式.所以对于上面的maxHeight是应该以小端模式来存放,具体情 ...

  9. java获取windows系统信息(CPU,内存,文件系统,硬盘大小)

    Java怎么获取windows系统信息,如CPU,内存,文件系统,硬盘大小? java实现这些功能的确有点麻烦,没有C语言方便.java在windows这方还是弱了一点.不过麻烦是麻烦点,针对这些功能 ...

最新文章

  1. Spring Boot+Vue从零开始搭建系统(一):项目前端_Vuejs环境搭建
  2. Iris——整合go-playground/validator参数校验Demo
  3. 关于表格动态添加行并处理相关表单元素的一些修改
  4. Flutter漫说:组件生命周期、State状态管理及局部重绘的实现(Inherit)
  5. 用 Flutter 开发真的NX
  6. charts 画饼图
  7. 计算机内页动画的作用是什么,滑环工作原理动画示意图有什么作用?
  8. 3DMax基础入门教程,命令面板的设置简介以及功能
  9. FFMPEG音视频解码流程MP4音视频文件流读取(转)
  10. linux下oracle imp,oracle中imp命令Linux下使用
  11. 怎么做网站?网站用什么服务器好?
  12. WSL2使用USB设备
  13. Weisfeiler-Lehman(WL)算法和WL Test的学习笔记
  14. 戴着脑电帽去旅游 ——浅谈旅游研究中脑电技术的应用
  15. python爬虫代码示例分享
  16. 【JZOJ A组】初音未来
  17. 古风古典雅致通用PPT模板
  18. 程序员的故事: 拉里 埃里森
  19. python提取首字母的函数_Oracle提取中文字符串拼音首字母函数
  20. 妻子照顾高位截瘫丈夫16年:和你一直到老挺知足

热门文章

  1. 微信摇一摇效果HTML,JavaScript+H5实现微信摇一摇功能
  2. 配对t检验的应用条件是什么_配对t检验的适用条件,独立样本T检验、配对T检...
  3. 软件工程课程设计项目总结与项目报告
  4. c1能力认证考试训练任务03-web基础与布局
  5. OpenCV (c++)使用KDTree时,得到正确结果后报Segmentation fault (core dumped)
  6. 优信php面试流程_php面试的的时候你被提过哪些问题?
  7. webstorm下载与激活
  8. Factory method ‘sqlSessionFactory‘ threw exception; nested exception is java.lang.NoSuchMethodError:
  9. C语言 实现99乘法口诀表
  10. PiFlow 朱小杰:科学家更爱开源 | Gitee 封面人物第 19 期