最近看《TCP/IP详解卷二:实现》的时候,发现mbuf:存储器缓存中使用到了一些union等结构,
然后花了一点力气将union、enum和结构体拿来对比学习了一下。
联合体union,可以看做是一种比较特殊的结构体,是一种在协议实现中用得比较多的一种结构,
由于它所有的变量共用一个内存空间,并且所需空间大小只取决于最大元素的类型,
所以联合体的好处是能节省内存空间。对于一些数据不能再同一时间同时被用到,则可以考虑用union。
例子1:
union state
{
char a;
short b;
int c;
}s;
int main(int argc, char *argv[])
{
s.c = 0x12345678;
printf("sizeof(s) = %d\n",sizeof(s));
printf("%p, %p, %p\n",&s.a,&s.b,&s.c);
printf("%#x, %#x, %#x\n",s.a,s.b,s.c);
return 0;
}
/************************************************
*gcc编译输出结果:
*sizeof(s) = 4;
*0x804a01c,0x804a01c,0x804a01c
*0x78,0x5678,0x12345678
*************************************************/
枚举enum,在实际问题中,有些变量的取值被限定在一个有限的范围内,那么可以使用枚举来列举变量的范围,从而限定变量。
那么从0开始自动+1赋值,如果对于赋值的元素,后面的元素在此基础上开始+1赋值。
例子2:
#include <stdio.h>
enum WeekDay
{
Monday = 1,
Tuesday,
Wednesday,
Thursday,
Friday = 10,
Saturday,
Sunday
}a,b,c,d;
int main(int argc, char *argv[])
{
a = Monday;
b = Friady;
c = Sunday;
d = 11;
printf("%p, %p, %p, %p\n",&a,&b,&c,&d);
printf("%d, %d, %d, %d\n",a,b,c,d);
return 0;
}
/******************************************************
*gcc编译输出结果:
*![gcc编译输出结果](https://img-blog.csdn.net/20150418160816875)
*g++编译输出结果:
*![g++编译输出结果](https://img-blog.csdn.net/20150418160851835)
******************************************************/
由此可见,对enum中变量的限定只在C++语法中起作用,在C语法中,给定义好的枚举型变量赋其他的整型值是没有问题的。
所以对已枚举型变量的限制对于C语言可以暂时不管,但是为了代码的可移植性和兼容性,最好按照C++的语法来使用。
最后来写一个比较常见判断系统大端小端的union例子:
#include <stdio.h>
union check
{
char ch;
int a;
}c;
int CheckSystem(void)
{
c.a = 1;
return (c.ch == 1);
}
int main(int argc, char * argv[])
{
if (CheckSystem() == 0)
printf("This is Big_endian system!\n");
else
printf("This is Little_endian system!\n");
return 0;
}
总的来说,对于C语言中的union和enum这两中类型如果在程序中运用的好,不仅能够提高程序的档次,还能够体现一个程序员的编程功底。
从mbuf结构中可以看出一些端倪。下面也把这段传说中的程序贴出来,让大家看看:
struct mbuf{
struct m_hdr m_hdr;
union{
struct {
struct pkthdr MH_pkthdr;
union{
struct m_ext MH_ext;
char MH_databuf[MHLEN];
}MH_dat;
}MH;
char M_databuf[MLEN];
}M_DAT;
};