C 结构体位域 bit field (小端)

2024-02-16 02:08
文章标签 结构 bit field 小端 体位

本文主要是介绍C 结构体位域 bit field (小端),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

运行环境为X86 64小端:

结构体中size最大的元素t0是int, 占四个字节,因此整个结构体是4字节对齐,结构体中的short是两字节对齐。

short占两个字节16bit,因此t1,t2,t3,t4共同占用short的两个字节。t5需要两字节对齐,单独占用两个字节。

因此整个结构体占用8个字节。

GDB通过x/8bx查看结构体8个字节,小端存放,高字节在高地址,低字节在低地址。

t0是0x00102030, 从低地址到高地址依次是: 0x30    0x20    0x10    0x00

t1,t2,t3,t4存放在同一个short两字节中,t4作为most significant,在内存中从低地址到高地址存放依次为t1,t2,t3,t4。

如果在GDB中以双字节打印这个short,显示顺序为t4t3t2t1,即0xdcba

如果以字节方式打印,由于short占用两个字节(高端字节t4t3,低端字节t2t1),高端字节存放在高地址,因此显示顺序为t2t1t4t3, 即0xba  0xdc

注意:不管何种方式打印,首先要明确的是t1t2t3t4是作为short类型存放的,然后再考虑各种方式打印这个short两字节的不同。

t5内容为0x000E, 小端存放为0x0E00

#include <stdio.h>
#include <string.h>typedef struct bit_field{unsigned int   t0;unsigned short t1 : 4;unsigned short t2 : 4;unsigned short t3 : 4;unsigned short t4 : 4;unsigned short t5 : 4;
}bf;void endian_check()
{int i = 0x1;unsigned char *p;p = (unsigned char *)&i;if (*p)printf("little endian\r\n");elseprintf("big endian\r\n");return;
}main()
{endian_check();printf("size of uint is: %d\r\n", sizeof(unsigned int));printf("size of ushort is: %d\r\n", sizeof(unsigned short));printf("size of bit_field structure is: %d\r\n", sizeof(bf));bf bf_test;memset(&bf_test, 0, sizeof(bf_test));bf_test.t0 = 0x102030;bf_test.t1 = 0x0A;bf_test.t2 = 0x0B;bf_test.t3 = 0x0C;bf_test.t4 = 0x0D;bf_test.t5 = 0x0E;
}

输出为:

little endian
size of uint is: 4
size of ushort is: 2
size of bit_field structure is: 8

 

通过GDB查看内存字节存放:

(gdb) p bf_test
$1 = {t0 = 1056816, t1 = 10, t2 = 11, t3 = 12, t4 = 13, t5 = 14}
(gdb) x/4hx &bf_test
0x7fffffffe230: 0x2030  0x0010  0xdcba  0x000e
(gdb) x/8bx &bf_test
0x7fffffffe230: 0x30    0x20    0x10    0x00    0xba    0xdc    0x0e    0x00

以下内容from http://mjfrazer.org/mjfrazer/bitfields/

How Endianness Effects Bitfield Packing

Hints for porting drivers.

Big endian machines pack bitfields from most significant byte to least.
Little endian machines pack bitfields from least significant byte to most.

When we read hexidecimal numbers ourselves, we read them from most significant byte to least. So reading big endian memory dumps is easer than reading little endian. When it comes to reading memory dumps of bitfields, it is even harder than reading integers.

Consider:

    union {unsigned short value;unsigned char byte[2];struct {unsigned short a : 4;unsigned short b : 4;unsigned short c : 4;unsigned short d : 4;} field;} u;

On a big endian machine, the first field is in the first nibble in memory. When we print out a memory dump's character hex values, say [ 0x12, 0x34 ], it is easy to see that a = 1, b = 2, c = 3 and d = 4.

On a little endian machine, a memory dump of [ 0x12, 0x34 ] would indicate that a = 2, b = 1, c = 4, and d = 3. This is because our 2-nibble, or 1 byte, hex value has transposed the pairs of nibbles. Remember that field a would go in the least significant bits, so if we set (a, b, c, d) = (1, 2, 3, 4) we would read the nibbles from least significant to most as 1 2 3 4, but the bytes as 0x21, 0x43. Interpreting this memory as a short gives us the value 0x4321.

These two figures illustrate how the nibble sized elements are packed into memory with the 16 bit field being laid out from MSB to LSB.

 

big endian examplelittle endian example
Big Endian LayoutLittle Endian Layout

注意:上图中

左图:对于大端来说,左侧为低地址,右侧为高地址。a为most significant, d为least significant

右图:对于小端来说,右侧为低地址,左侧为高地址。a为least significant, d为most significant

Now consider:

    union {unsigned short value;unsigned char byte[2];struct {unsigned short a : 1;unsigned short b : 2;unsigned short c : 3;unsigned short d : 4;unsigned short e : 5;} field;} v;

Again, the bits are pack from most significant on a big endian machine and least significant on a little endian machine. Interpreted as a short, the bitfield 'a' adds 0x0001 to 'value' on a little endian machine and 0x8000 on a big endian machine. The unused bit is left to the end of interpreting the struct, so it is the MSB on a little endian machine and the LSB on a big endian machine.

These two figures illustrate how the differently sized elements are packed into memory with the 16 bit field being laid out from MSB to LSB.

注意:上图中

左图:对于大端来说,左侧为低地址,右侧为高地址。a为most significant, d为least significant

右图:对于小端来说,右侧为低地址,左侧为高地址。a为least significant, d为most significant

 

参考:

http://mjfrazer.org/mjfrazer/bitfields/

 

这篇关于C 结构体位域 bit field (小端)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/713198

相关文章

usaco 1.3 Mixing Milk (结构体排序 qsort) and hdu 2020(sort)

到了这题学会了结构体排序 于是回去修改了 1.2 milking cows 的算法~ 结构体排序核心: 1.结构体定义 struct Milk{int price;int milks;}milk[5000]; 2.自定义的比较函数,若返回值为正,qsort 函数判定a>b ;为负,a<b;为0,a==b; int milkcmp(const void *va,c

自定义类型:结构体(续)

目录 一. 结构体的内存对齐 1.1 为什么存在内存对齐? 1.2 修改默认对齐数 二. 结构体传参 三. 结构体实现位段 一. 结构体的内存对齐 在前面的文章里我们已经讲过一部分的内存对齐的知识,并举出了两个例子,我们再举出两个例子继续说明: struct S3{double a;int b;char c;};int mian(){printf("%zd\n",s

OpenCV结构分析与形状描述符(11)椭圆拟合函数fitEllipse()的使用

操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C++11 算法描述 围绕一组2D点拟合一个椭圆。 该函数计算出一个椭圆,该椭圆在最小二乘意义上最好地拟合一组2D点。它返回一个内切椭圆的旋转矩形。使用了由[90]描述的第一个算法。开发者应该注意,由于数据点靠近包含的 Mat 元素的边界,返回的椭圆/旋转矩形数据

[论文笔记]LLM.int8(): 8-bit Matrix Multiplication for Transformers at Scale

引言 今天带来第一篇量化论文LLM.int8(): 8-bit Matrix Multiplication for Transformers at Scale笔记。 为了简单,下文中以翻译的口吻记录,比如替换"作者"为"我们"。 大语言模型已被广泛采用,但推理时需要大量的GPU内存。我们开发了一种Int8矩阵乘法的过程,用于Transformer中的前馈和注意力投影层,这可以将推理所需

C语言程序设计(选择结构程序设计)

一、关系运算符和关系表达式 1.1关系运算符及其优先次序 ①<(小于) ②<=(小于或等于) ③>(大于) ④>=(大于或等于 ) ⑤==(等于) ⑥!=(不等于) 说明: 前4个优先级相同,后2个优先级相同,关系运算符的优先级低于算术运算符,关系运算符的优先级高于赋值运算符 1.2关系表达式 用关系运算符将两个表达式(可以是算术表达式或关系表达式,逻辑表达式,赋值表达式,字符

Science|癌症中三级淋巴结构的免疫调节作用与治疗潜力|顶刊精析·24-09-08

小罗碎碎念 Science文献精析 今天精析的这一篇综述,于2022-01-07发表于Science,主要讨论了癌症中的三级淋巴结构(Tertiary Lymphoid Structures, TLS)及其在肿瘤免疫反应中的作用。 作者类型作者姓名单位名称(中文)通讯作者介绍第一作者Ton N. Schumacher荷兰癌症研究所通讯作者之一通讯作者Daniela S. Thomm

oracle11.2g递归查询(树形结构查询)

转自: 一 二 简单语法介绍 一、树型表结构:节点ID 上级ID 节点名称二、公式: select 节点ID,节点名称,levelfrom 表connect by prior 节点ID=上级节点IDstart with 上级节点ID=节点值 oracle官网解说 开发人员:SQL 递归: 在 Oracle Database 11g 第 2 版中查询层次结构数据的快速

Tomcat下载压缩包解压后应有如下文件结构

1、bin:存放启动和关闭Tomcat的命令的路径。 2、conf:存放Tomcat的配置,所有的Tomcat的配置都在该路径下设置。 3、lib:存放Tomcat服务器的核心类库(JAR文件),如果需要扩展Tomcat功能,也可将第三方类库复制到该路径下。 4、logs:这是一个空路径,该路径用于保存Tomcat每次运行后产生的日志。 5、temp:保存Web应用运行过程中生成的临时文件

C和指针:结构体(struct)和联合(union)

结构体和联合 结构体 结构体包含一些数据成员,每个成员可能具有不同的类型。 数组的元素长度相同,可以通过下标访问(转换为指针)。但是结构体的成员可能长度不同,所以不能用下标来访问它们。成员有自己的名字,可以通过名字访问成员。 结构声明 在声明结构时,必须列出它包含的所有成员。 struct tag {member-list} variable-list ; 定义一个结构体变量x(包含

MonoHuman: Animatable Human Neural Field from Monocular Video 翻译

MonoHuman:来自单目视频的可动画人类神经场 摘要。利用自由视图控制来动画化虚拟化身对于诸如虚拟现实和数字娱乐之类的各种应用来说是至关重要的。已有的研究试图利用神经辐射场(NeRF)的表征能力从单目视频中重建人体。最近的工作提出将变形网络移植到NeRF中,以进一步模拟人类神经场的动力学,从而动画化逼真的人类运动。然而,这种流水线要么依赖于姿态相关的表示,要么由于帧无关的优化而缺乏运动一致性