结构体的位域

在看一个构造ip包头的的代码时,出现了如下情况。

struct ip{
    unsigned char version:4;       // 版本
    unsigned char hlen:4;        // 首部长度
    unsigned char tos;             // 服务类型
    unsigned short len;         // 总长度
    unsigned short id;            // 标识符
    unsigned short offset;        // 标志和片偏移
    unsigned char ttl;            // 生存时间
    unsigned char protocol;     // 协议
    unsigned short checksum;    // 校验和
    struct in_addr ipsrc;        // 32位源ip地址
    struct in_addr ipdst;       // 32位目的ip地址
};

因为ip包头的版本字段和首部长度字段各自只占一个字节中的四个bit位,所以这里使用了位域的写法。

下面给出一个位域使用的例子,看了这个例子应该就理解位域的使用了。

#include 
#include 
int main()
{
    struct bs
    {
        unsigned a:1;
        unsigned b:3;
        unsigned c:4;
    }bit,*pbit;

    bit.a=1;
    bit.b=7;
    bit.c=15;
    printf("%d,%d,%d\n",bit.a,bit.b,bit.c);            //输出:1,7,15
    pbit=&bit;
    pbit->a=0;
    pbit->b&=3;
    pbit->c|=1;
    printf("%d,%d,%d\n",pbit->a,pbit->b,pbit->c );      //输出:0,3,15
}

程序的6,7,8三行分别给三个位域赋值

应注意赋值不能超过该位域的允许范围,超过时,仅将等号右侧值的低位赋值给位域)

比如说这个例子中,位域a只占一个bit位的大小,所以只能正确赋值整形的0和1,如果赋值更大的数字,发生截断。之后的打印整形不再正确。如将a赋值为2,那么编译器warning

test.c:12:10: warning: implicit truncation from 'int' to bitfield changes value
      from 2 to 0 [-Wbitfield-constant-conversion]
    bit.a=2;
         ^~
1 warning generated.

之后打印结果为a,发现结果为0,因为二进制位发生了截断。

同理b只有三位,能容纳的最大数字是7。

你可能感兴趣的:(c++)