zoukankan      html  css  js  c++  java
  • C语言中的位域(bitfield)概念

    一、位域简介  

    接触过Linux内核网络协议栈的人,大概都见过位域的表达方式。 如下是摘自Linux内核代码(include/linux/tcp.h)中关于tcp头部的定义:

     1 struct tcphdr {
    2 __be16 source;
    3 __be16 dest;
    4 __be32 seq;
    5 __be32 ack_seq;
    6 #if defined(__LITTLE_ENDIAN_BITFIELD)
    7 __u16 res1:4,
    8 doff:4,
    9 fin:1,
    10 syn:1,
    11 rst:1,
    12 psh:1,
    13 ack:1,
    14 urg:1,
    15 ece:1,
    16 cwr:1;
    17 #elif defined(__BIG_ENDIAN_BITFIELD)
    18 __u16 doff:4,
    19 res1:4,
    20 cwr:1,
    21 ece:1,
    22 urg:1,
    23 ack:1,
    24 psh:1,
    25 rst:1,
    26 syn:1,
    27 fin:1;
    28 #else
    29 #error "Adjust your <asm/byteorder.h> defines"
    30 #endif
    31 __be16 window;
    32 __sum16 check;
    33 __be16 urg_ptr;
    34 };

       位域的表达方式就是变量名:位数。 从上面tcphdr的定义可以看出,位域是跟实现有关的。 下面是C1999标准中关于位域的一个样例:

    EXAMPLE 3 The following obscure constructions
    typedef signed int t;
    typedef int plain;
    struct tag {
    unsigned t:4;
    const t:5;
    plain r:5;
    };
    declare a typedef name t with type signed int, a typedef name plain with type int, and a structure
    with three bit-field members, one named t that contains values in the range [0, 15], an unnamed constqualified
    bit-field which (if it could be accessed) would contain values in either the range [−15, +15] or
    [−16, +15], and one named r that contains values in one of the ranges [0, 31], [−15, +15], or [−16, +15].
    (The choice of range is implementation-defined.) The first two bit-field declarations differ in that
    unsigned is a type specifier (which forces t to be the name of a structure member), while const is a
    type qualifier (which modifies t which is still visible as a typedef name).

      样例中给出了几个匿名的结构体成员, 如文中解释的,位域成员的取值范围是跟实现相关的。 我对由位域构成的结构体所占内存的大小比较感兴趣,就用sizeof()测试了一下,如下: 

     1 #include<stdio.h>
    2 #include<stdlib.h>
    3 #include<string.h>
    4 /*
    5 **Sample code by virHappy
    6 */
    7
    8 typedef signed int t;
    9 typedef int plain;
    10
    11 //anoymous member
    12 struct tag {
    13 unsigned t:4;
    14 const t:5;
    15 plain r:5;
    16 };
    17 // member is char
    18 struct rec {
    19 unsigned char a:1;
    20 unsigned char b:1;
    21 unsigned char c:1;
    22 unsigned char d:1;
    23 };
    24
    25 // member is unsigned int
    26 struct rec_int {
    27 unsigned int a:1;
    28 unsigned int b:1;
    29 unsigned int c:1;
    30 unsigned int d:1;
    31 };
    32
    33
    34 #define TEST_AND_SET_BIT(x) \
    35 do{ \
    36 if ((x)) { \
    37 printf("bit alread set.\n"); \
    38 } else { \
    39 (x) = 1; \
    40 } \
    41 }while(0)
    42
    43 int main()
    44 {
    45 struct tag st;
    46 struct rec sr;
    47
    48 printf("size of tag is: %d\n", sizeof(st));
    49 printf("size of rec is: %d\n", sizeof(sr));
    50 printf("size of rec is: %d\n", sizeof(struct rec_int));
    51 printf("size of rec is: %d\n", sizeof(int));
    52
    53 memset(&sr, 0, sizeof(struct rec));
    54 TEST_AND_SET_BIT(sr.a);
    55 TEST_AND_SET_BIT(sr.b);
    56 TEST_AND_SET_BIT(sr.c);
    57 TEST_AND_SET_BIT(sr.d);
    58
    59 TEST_AND_SET_BIT(sr.a);
    60 TEST_AND_SET_BIT(sr.b);
    61 TEST_AND_SET_BIT(sr.c);
    62 TEST_AND_SET_BIT(sr.d);
    63 return 0;
    64 }

    输出为:

    root@host]# gcc -Wall bitfield.c  -o bf
    [root@host]# ./bf
    size of tag is: 4
    size of rec is: 1
    size of rec is: 4
    size of rec is: 4
    bit alread set.
    bit alread set.
    bit alread set.
    bit alread set.

     结果显示由int类型说明符修饰的位域成员构成的结构体为4byte, 由char类型说明符修改的位域成员构成的结构体为1byte,即使实际上只声明了4个位长度大小的成员。 

      

    二、 位域的作用

      1.  在看一些rfc文档时,关于包结构部分的描述, 常常看到具体的某一位具有特定的功能。而内核的网络协议栈中对应的实现就是通过位域来实现的。

      2.  配置文件解析时, 有时候需要比较新的配置和已有的配置的区别, 这时需要做一些标记。 位域在这个时候就派上了用场。 优点的是占内存少。

      3. 其它?



  • 相关阅读:
    nginx.conf文件
    本地apache 可以正常访问,lnmp服务器访问404错误
    PHP网站从Apache转移到Nginx后产生404错误的原因和解决办法
    CGI,FAST-CGI,PHP-FPM的区别
    Lnmp修改php.ini配置
    APACHE服务器出现No input file specified.的完美解决方案
    EXCEL常用函数详解
    chrome extensions
    C++使用OLE高速读写EXCEL的源码
    C++读写EXCEL文件OLE,java读写excel文件POI 对比
  • 原文地址:https://www.cnblogs.com/quiet/p/2394349.html
Copyright © 2011-2022 走看看