hanwe 发表于 2022-10-13 20:00

为什么还要使用位段呢?

最近在学习Linux,发现源代码里不少结构体都用到位段,但我觉得使用位段并没有优势,虽然节省了一些数据空间,但给位段赋值需要更多的指令,不但代码空间不会减少,而且还增加了执行时间。看下面的例子:
      1.不使用位段
struct test
{
    unsigned int a;
unsigned int b;
unsigned int c;
};
int main()
{
struct test temp;
unsigned char n=sizeof(temp);
temp.a=6;
temp.b=8;
temp.c=18;
}
keil uVision4 里面编译的汇编代码是:
      11:         struct test temp;
0x000000E0E24DD00CSUB       R13,R13,#0x0000000C
      12:         unsigned char n=sizeof(temp);
0x000000E4E3A0100CMOV       R1,#0x0000000C
      13:         temp.a=6;
0x000000E8E3A00006MOV       R0,#0x00000006
0x000000ECE58D0000STR       R0,
      14:         temp.b=8;
0x000000F0E3A00008MOV       R0,#0x00000008
0x000000F4E58D0004STR       R0,
      15:         temp.c=18;
0x000000F8E3A00012MOV       R0,#0x00000012
0x000000FCE58D0008STR       R0,

2.使用位段
struct test
{
    unsigned int a:6;
unsigned int b:8;
unsigned int c:18;
};
int main()
{
struct test temp;
unsigned char n=sizeof(temp);
temp.a=6;
temp.b=8;
temp.c=18;
}
      11:         unsigned char n=sizeof(temp);
0x000000E4E3A01004MOV       R1,#0x00000004
      12:         temp.a=6;
0x000000E8E59D0000LDR       R0,
0x000000ECE3C0003FBIC       R0,R0,#0x0000003F
0x000000F0E3800006ORR       R0,R0,#0x00000006
0x000000F4E58D0000STR       R0,
      13:         temp.b=8;
0x000000F8E59D0000LDR       R0,
0x000000FCE3C00DFFBIC       R0,R0,#0x00003FC0
0x00000100E3800C02ORR       R0,R0,#0x00000200
0x00000104E58D0000STR       R0,
      14:         temp.c=18;
0x00000108E59D0000LDR       R0,
0x0000010CE1A00900MOV       R0,R0,LSL #18
0x00000110E1A00920MOV       R0,R0,LSR #18
0x00000114E3800912ORR       R0,R0,#0x00048000
0x00000118E58D0000STR       R0,

    那么,为什么还要使用位段呢?

xxrs 发表于 2022-10-13 20:02

对寄存器定义时有用,方便。

hanwe 发表于 2022-10-13 20:06

难道要这样访问寄存器:struct SFRValue *regvalue=(unsigned SFRValue *)(resiger_address)?

jiajs 发表于 2022-10-13 20:10


换一种写法试试:

2.使用位段
struct test
{
unsigned int a:6;
unsigned int a:8;
unsigned int a:18;
};
更多操作

hanwe 发表于 2022-10-13 20:12


可以这样写吗?
试了一下,结果是:
error:#101: "a" has already been declared in the current scope

yszong 发表于 2022-10-13 20:14

那是ARM本身对位支持不好,不等于其它MCU支持不好

zwll 发表于 2022-10-13 20:17


使用位段可以增加代码的可阅读性
效率问题,使用位段与不使用位段相差无几
至于你举的例子,只能说是为位段而位段,无实际意义

pengf 发表于 2022-10-13 20:21


如果CPU支持位寻址的,那么使用位段的效率也是很高的。

hanwe 发表于 2022-10-13 20:23

支持位寻址的CPU是用一个地址寻址一个位,没办法用一个地址寻址一个位段。

stly 发表于 2022-10-13 20:29

使用位段只是为了省点存储空间,从反汇编代码也可以看出来,不使用位段那个结构要用12字节空间,而使用位段后只用4字节。

supernan 发表于 2022-10-13 20:32

至于效率方面,肯定会有所下降的,有得必有失嘛。

wuhany 发表于 2022-10-13 20:34

对于存储来说,定义了变量位数能减省RAM的消耗

shimx 发表于 2022-10-13 20:37

但是CPU运行计算的次数要变多

yufe 发表于 2022-10-13 20:40

对寄存器定义时有用,方便。

午夜粪车 发表于 2022-10-13 20:43

可读性强,移植方便

tpgf 发表于 2022-11-4 15:23

位段是 C 语言特有的数据结构, 它允许我们定义一个由位组成的段, 并可为它赋以一个名字。

qcliu 发表于 2022-11-4 15:35

使用位段时, 必须注意下列事项:

在某些机器上, 位段总是作为 unsigned 处理, 而不管它们是否被说明成 unsigned 的。
大多数C 编译器都不支持超过一个字长的位段。
位段不可标明维数; 即, 不能说明位段数组, 例如 flag:l。
最后, 不可以取位段地址。原因是, 在这种情况不, 显然没有称作为 "位段指针" 类型的变量。

drer 发表于 2022-11-4 15:49

1.位段的成员可以是int 、 unsigned int 、signed int 、或者char类型
2.位段的空间上是按照需要以四个字节或者一个字节的方式来开辟的(先开辟4(1)个字节,不够再开辟4(1)个字节)
3.位段涉及很多不确定因素,位段是不跨平台的

coshi 发表于 2022-11-4 16:06

1.int位段被当做有符号数还是无符号数是不确定的
2.位段中最大位的数目不能确定
3.位段中的成员在内存中从左向右分配,还是从右向左分配,标准中尚未规定
4.当一个结构体包含两个位段,第二个位段比较大,无法容纳于第一个位段所剩的bit位时,是舍弃还是利用,也是未规定的

kxsi 发表于 2022-11-4 16:15

相较于结构,位段可以起到相同的效果,而且可以节省空间,但是有不能跨平台的局限性
页: [1] 2
查看完整版本: 为什么还要使用位段呢?