1.通过结构体, 从函数中返回多个数据元素
例1:
2.结构体可以映射数据的组织方式
例1.
例3.
例4:
3.以面向对象的方式编程
通过结构体将相关数据和函数指针封装在一起, 来模拟类的字段和方法, 从而创建类似对象的实体.
例1:
例2:
例1:
/* 函数同时返回包含秒和微秒的时间差 */
typedef struct {
int tv_sec;
int tv_usec;
} timeval;
static timeval difftv(timeval a, timeval b)
{
static timeval diff;
diff.tv_sec = b.tv_sec - a.tv_sec;
if ((diff.tv_usec = b.tv_usec - a.tv_usec) < 0) {
diff.tv_sec--;
diff.tv_usec += 1000000;
}
return diff;
}
2.结构体可以映射数据的组织方式
例1.
/*fxp_cb_nop表示了Intel EtherExpress网卡的一个控制块*/
struct fxp_cb_nop {
void *fill[2];
volatile u_int16_t cb_status;
volatile u_int16_t cb_command;
volatile u_int32_t link_addr;
};
volatile 修饰符用来表明底层的内存字段将被程序之外的实体(上例为网卡)使用, 从而禁止编译器对其进行移除冗余引用之类的优化.例2.结构体中使用bit-field语法定义只占几个bit的成员:
/* 使用位域(bit-field)来划分出精确的bit区域, 以保存指定设备上的特定数据 */
typedef struct {
unsigned int one:1;
unsigned int two:3;
unsigned int three:10;
unsigned int four:5;
unsigned int :2;
unsigned int five:8;
unsigned int six:8;
} demo_type;
int main(void)
{
demo_type s = { 1, 5, 513, 17, 129, 0x81 };
printf("sizeof demo_type = %u\n", sizeof(demo_type));
printf("values: s=%u,%u,%u,%u,%u,%u\n",
s.one, s.two, s.three, s.four, s.five, s.six);
return 0;
}
例3.
struct fxp_cb_config {
[...]
volatile u_int8_t byte_count:6,
:2;
volatile u_int8_t rx_fifo_limit:4,
tx_fifo_limit:3,
:1;
};
用来传递数据的byte_count占据了6bit的空间, 而数据的接收者和传送者的FIFO队列限制在硬件设备上分别占据了4bit和3bit的空间. 那个':2'和':1'是未命名的bit-field, 即使不写未命名的bit-field, 编译器也可能在两个成员之间插入填充位. 这样使访问效率提高.例4:
/* TCP报文的经典定义 */
struct tcphdr {
u_int16_t th_sport; /* source port */
u_int16_t th_dport; /* destination port */
tcp_seq th_seq; /* sequence number */
tcp_seq th_ack; /* acknowledgement number */
[...]
};
3.以面向对象的方式编程
通过结构体将相关数据和函数指针封装在一起, 来模拟类的字段和方法, 从而创建类似对象的实体.
例1:
/* 结构体domain用来表示网络协议(Internet, SNA, IPX)中的不同的域
* 它封装了与特定域相关的数据(比如域所属的家族dom_family)和
* 操作这些数据的方法(比如路由表的初始化方法) */
struct domain {
int dom_family; /* AF_xxx */
char *dom_name;
void (*dom_init)(void); /* initialize domain data structures */
[...]
int (*dom_rtattach)(void **, int);
/* initialize routing table */
int dom_rtoffset; /* an arg to rtattach, in bits */
int dom_maxrtkey; /* for routing layer */
};
该结构体类型的变量或指针(更常见)在完成初始化以后, 就可以像C++或Java对象那样
使用了.
for (dom = domains; dom; dom = dom->dom_next)
if (dom->dom_family == i && dom->dom_rtattach) {
dom->dom_rtattach((void **)&nep->ne_rtable[i],
dom->dom_rtoffset);
break;
[...]
}
例2:
/* 因为同一类型的对象共享了相同的方法(函数指向了相同的函数地址)
* 所以, "对象"通常只存储一个指向另一结构体的指针,
* 由这个结构体负责存储指向实际方法的指针,
* 从而达到在不同对象之间共享方法指针的目的 */
struct file {
[...]
short f_type; /* descriptor type */
short f_count; /* reference count */
short f_msgcount; /* reference from message quene */
struct ucred *f_cred; /* credentials associated with descriptor */
struct fileops {
int (*fo_read)(struct file *fp, struct uio *uio,
struct ucred *cred);
int (*fo_write)(struct file *fp, struct uio *uio,
struct ucred *cred);
int (*fo_ioctl)(struct file *fp, u_long com,
caddr_t data, struct proc *p);
int (*fo_poll)(struct file *fp, int events,
struct proc *p);
int (*fo_close)(struct file *fp, struct proc *p);
} *f_ops;
off_t f_offset;
caddr_t f_data; /* vnode or socket */
}
作者:byguess 发表于2013-4-22 12:12:17 原文链接
阅读:29 评论:0 查看评论