打印

C语言里的位段

[复制链接]
4326|11
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
hxlwjn|  楼主 | 2010-4-21 10:12 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 hxlwjn 于 2010-4-21 10:14 编辑

最近在学习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;
0x000000E0  E24DD00C  SUB       R13,R13,#0x0000000C
    12:         unsigned char n=sizeof(temp);
0x000000E4  E3A0100C  MOV       R1,#0x0000000C
    13:         temp.a=6;
0x000000E8  E3A00006  MOV       R0,#0x00000006
0x000000EC  E58D0000  STR       R0,[R13]
    14:         temp.b=8;
0x000000F0  E3A00008  MOV       R0,#0x00000008
0x000000F4  E58D0004  STR       R0,[R13,#0x0004]
    15:         temp.c=18;
0x000000F8  E3A00012  MOV       R0,#0x00000012
0x000000FC  E58D0008  STR       R0,[R13,#0x0008]

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);
0x000000E4  E3A01004  MOV       R1,#0x00000004
    12:         temp.a=6;
0x000000E8  E59D0000  LDR       R0,[R13]
0x000000EC  E3C0003F  BIC       R0,R0,#0x0000003F
0x000000F0  E3800006  ORR       R0,R0,#0x00000006
0x000000F4  E58D0000  STR       R0,[R13]
    13:         temp.b=8;
0x000000F8  E59D0000  LDR       R0,[R13]
0x000000FC  E3C00DFF  BIC       R0,R0,#0x00003FC0
0x00000100  E3800C02  ORR       R0,R0,#0x00000200
0x00000104  E58D0000  STR       R0,[R13]
    14:         temp.c=18;
0x00000108  E59D0000  LDR       R0,[R13]
0x0000010C  E1A00900  MOV       R0,R0,LSL #18
0x00000110  E1A00920  MOV       R0,R0,LSR #18
0x00000114  E3800912  ORR       R0,R0,#0x00048000
0x00000118  E58D0000  STR       R0,[R13]

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

相关帖子

沙发
heyan| | 2010-4-21 10:23 | 只看该作者
对寄存器定义时有用,方便。

使用特权

评论回复
板凳
hxlwjn|  楼主 | 2010-4-21 10:33 | 只看该作者
本帖最后由 hxlwjn 于 2010-4-21 14:27 编辑

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

使用特权

评论回复
地板
冷漠| | 2010-4-21 10:35 | 只看该作者
换一种写法试试:

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

使用特权

评论回复
5
ayb_ice| | 2010-4-21 10:39 | 只看该作者
那是ARM本身对位支持不好,不等于其它MCU支持不好

使用特权

评论回复
6
hxlwjn|  楼主 | 2010-4-21 10:41 | 只看该作者
4# 冷漠
可以这样写吗?
试了一下,结果是:
error:  #101: "a" has already been declared in the current scope

使用特权

评论回复
7
lxyppc| | 2010-4-21 11:19 | 只看该作者
使用位段可以增加代码的可阅读性
效率问题,使用位段与不使用位段相差无几
至于你举的例子,只能说是为位段而位段,无实际意义

使用特权

评论回复
8
znmcu| | 2010-4-21 12:08 | 只看该作者
关于C语言中的位段,可以到我网站 “资料下载” 中参考
振南带你精通C51【PDF文档教程】之【5】《位操作》之《位段的用法》
http://www.znmcu.cn/softshow.asp?id=73

使用特权

评论回复
9
hxlwjn|  楼主 | 2010-4-21 14:44 | 只看该作者
本帖最后由 hxlwjn 于 2010-4-21 15:03 编辑

8# znmcu

看了你的《位段的用法》,觉得几个地方好像有点问题:
  “同时写出来的程序也会占用更少资源,这也就意味着您的程序将拥有更 高
的运行效率。”
   也许可以占用更少资源,但更高的运行效率,不敢苟同。

“ 从上面已经大致可以了解了位段的使用方法了。形如结构体,位长的定义用unsigned或 int 来定义。如 unsigned a:3 或 unsigned int a:3 定义了定义 a 为位长为 3位段成员。”

除了浮点类型,用其他基本数据类型也是可以定义位长的。
“以下几种定义都是不正确的:
struct bits
{
unsigned a:9;// 超过了存储单元的长度这样定义应该是可以的,如果这里的unsigned==unsigned int
unsigned b:1;
};"

使用特权

评论回复
10
zhuhai2004| | 2010-4-21 15:33 | 只看该作者
如果CPU支持位寻址的,那么使用位段的效率也是很高的。

使用特权

评论回复
11
hxlwjn|  楼主 | 2010-4-21 17:09 | 只看该作者
10# zhuhai2004

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

使用特权

评论回复
12
hgjinwei| | 2010-4-21 19:27 | 只看该作者
使用位段只是为了省点存储空间,从反汇编代码也可以看出来,不使用位段那个结构要用12字节空间,而使用位段后只用4字节。
至于效率方面,肯定会有所下降的,有得必有失嘛。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

5

主题

58

帖子

0

粉丝