转:关于C语言的位域(bitfield)

原文地址:http://www.cppblog.com/ichenq/archive/2009/07/12/89888.aspx

 

基本知识见这里这里, 已经说得很清楚,不过是洋文,简单归纳一下:

(1), 定义语法:类型 标志符(optional) : 常量表达式

(2), 类型必须为unsigned, signed int 或者int, 常量表达式的值不能为负且不能超过类型能够表示的范围;

(3), 不允许出现位域数组,指向位域的指针(&运算符)和以位域为返回值的函数;

(4), 没有标志符的位域不能被引用,且长度为0时编译器保证下一个位域从下一个存储单元开始存放(一般为int的长度);

 

一些讨论:

1,类型

虽然很多书上都说位域的类型只能为unsigned和int,但是在编译器里实践一下就会发现只要是整型(char, long)都可以作为位域的类型,只要冒号后面定义的常量数值不大于此类型能够表示的范围。从文档看这个是微软对ANSI C标准的扩充(Microsoft Specific),不过我还没有在Linux平台下面进一步实践以验证。

 

2,长度

看到很多博客上写道"位域的长度不能大于一个字节的长度,也就是说不能超过8位二进位"。如上所述,只要长度不超过类型可以表示的范围都是正确的。另外一点就是关于unsigned的问题,对于下面的代码,

typedef  struct  tag
{

        
char  hour :  4 ;
        unsigned second : 
6 ;
        unsigned minute : 
6 ;
}Time;

printf(
" %d/n " sizeof (Time));

在gcc下的输出是4,在vc下的输出是8。

原因是gcc把unsigned类型当成unsigned short来处理,Time.hour和Time.second共同占用一个unsigned short单元,minute独占一个unsigned short单元,再加上对其所需的空白,总共是2个unsigned short, 则sizeof为4。

而VC把位域的unsigned类型当做unsigned int,所以Time占用2个unsigned int,sizeof值为8。

 

3,示例

下面是一段在论坛上发现的代码,

union 
{
    
struct  
    {
        
char  a :  1 ;
        
char  b :  2 ;
        
char  c :  3 ;
    }d;

    
char  e;
}f;

f.e
=   1 ;
printf(
" %d/n " , f.d.a);

Intel x86的机器是按little-endian的字节顺序存储数据(点击for详细),所以d中的位域在内存中放置顺序为 cccbba ,

当执行完 f.e = 1 这条语句后,d的最低有效位(及位域a)的值为1。

这时我就出现了疑问,为什么打印的最后结果是-1而不是1?

不过最后终于解决了这个问题,因为位域a定义的类型是signed char,是一个有符号数,所以尽管a只有1位,还是要进行符号扩展。1是做为补码存在,加一再取反就得到值-1。

如果将a的类型定义为unsigned char即可得到结果为1。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C语言中的位(bit-field)是一种数据结构,用于将一个整型数据类型拆分成多个不同的位来存储不同的信息。位可以用于节省内存空间,提高程序性能,或者定义一些特殊的数据类型。 位通常与结构体一起使用,结构体中的每个成员可以使用不同的位来表示不同的信息。定义一个位的语法格式如下: ``` struct { type [member_name] : width; }; ``` 其中,type 表示位的数据类型,member_name 表示成员的名称,width 表示该成员占用的位数。 以下是一个例子: ``` #include <stdio.h> struct { unsigned int age : 3; unsigned int sex : 1; } person; int main() { person.age = 5; person.sex = 1; printf("person.age: %d\n", person.age); printf("person.sex: %d\n", person.sex); return 0; } ``` 在这个例子中,我们定义了一个名为 person 的结构体,其中包含两个位成员 age 和 sex。age 占用 3 位,sex 占用 1 位。 在主函数中,我们为 person 的 age 和 sex 成员分别赋值,然后使用 printf 函数输出这两个成员的值。输出结果为: ``` person.age: 5 person.sex: 1 ``` 由于 age 只占用了 3 位,所以它的取值范围为 0 到 7。sex 只占用了 1 位,所以它的取值范围为 0 或 1。 需要注意的是,位的使用可能会受到机器硬件的限制,不同的编译器可能会对位的实现方式有所不同。因此,在使用位时需要谨慎考虑其可移植性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值