初学c语言开发的小伙伴们,在学习的过程中,可能会发现在有些结构体定义里的变量定义后面出现冒号跟着数字的情况,例如下面这个结构体的定义,
struct ngx_event_s {
void *data;
unsigned write:1;
unsigned accept:1;
/* used to detect the stale events in kqueue and epoll */
unsigned instance:1;
/*
* the event was passed or would be passed to a kernel;
* in aio mode - operation was posted.
*/
unsigned active:1;
unsigned disabled:1;
/* the ready event; in aio mode 0 means that no operation can be posted */
unsigned ready:1;
unsigned oneshot:1;
/* aio operation is complete */
unsigned complete:1;
unsigned eof:1;
unsigned error:1;
unsigned timedout:1;
unsigned timer_set:1;
unsigned delayed:1;
unsigned deferred_accept:1;
/* the pending eof reported by kqueue, epoll or in aio chain operation */
unsigned pending_eof:1;
unsigned posted:1;
unsigned closed:1;
/* to test on worker exit */
unsigned channel:1;
unsigned resolver:1;
unsigned cancelable:1;
#if (NGX_HAVE_KQUEUE)
unsigned kq_vnode:1;
/* the pending errno reported by kqueue */
int kq_errno;
#endif
/*
* kqueue only:
* accept: number of sockets that wait to be accepted
* read: bytes to read when event is ready
* or lowat when event is set with NGX_LOWAT_EVENT flag
* write: available space in buffer when event is ready
* or lowat when event is set with NGX_LOWAT_EVENT flag
*
* iocp: TODO
*
* otherwise:
* accept: 1 if accept many, 0 otherwise
* read: bytes to read when event is ready, -1 if not known
*/
int available;
ngx_event_handler_pt handler;
#if (NGX_HAVE_IOCP)
ngx_event_ovlp_t ovlp;
#endif
ngx_uint_t index;
ngx_log_t *log;
ngx_rbtree_node_t timer;
/* the posted queue */
ngx_queue_t queue;
#if 0
/* the threads support */
/*
* the event thread context, we store it here
* if $(CC) does not understand __thread declaration
* and pthread_getspecific() is too costly
*/
void *thr_ctx;
#if (NGX_EVENT_T_PADDING)
/* event should not cross cache line in SMP */
uint32_t padding[NGX_EVENT_T_PADDING];
#endif
#endif
};
当你第一次见到这种情况,于是一脑门子的问号就浮现出来了。。。
这是什么东东,我怎么从来没见过呢,为什么用这个东东。。。
我们一个一个来看,
首先,我们认识一下这是个什么东东。英文中,称结构体内这种有预定义宽度类型的成员变量为 bit fields ,翻译过来,称位域。一个位域可以不只占一个 bit 位,譬如,你需要一个存储值范围为0 到 7 的变量,那么你需要定义 3 bit 位宽度的位域,
struct { unsigned int age : 3; } Age;
由此,我们看一下一个位域的声明(Bit Field Declaration),
struct {
type [member_name] : width ;
};
可以看到,一个位域的变量元素,包括,
type ,位域的类型可以是, int, signed int, 或者 unsigned int ;
member_name ,位域名;
width ,位域中的位数;宽度必须小于或等于指定类型的位宽。
那为何要用这种东东呢?节省存储空间。想象一下,你需要构造一个结构体,其内包含的成员,只需要少量的 bit 位,就可以满足对事物的描述。像这样的情况,采用位域可以相对节省不少的存储空间。