1.联合与结构
上一节中我们使用struct
关键词,组合不同的类型让它们成为一个新的类型。
例如,我们想组合char
、short
、long long
,可以像如下代码写法。
struct {
char c;
short s;
long long ll;
}s;
对于结构struct
的讨论在上一节已经够多了。在一节中,我们讨论和结构语法类似的联合,关键词为union
。
联合char
、short
、long long
,可以像如下代码写法。
union {
char c;
short s;
long long ll;
}u;
联合的语法非常类似于结构的语法,几乎仅仅换了一个关键词而已。让我们来看看,它们之间有什么差别?
我们先使用sizeof
分别测试一下它们的大小。
struct {
char c;
short s;
long long ll;
}s;
union {
char c;
short s;
long long ll;
}u;
printf("sizeof s %d\n", sizeof(s));
printf("sizeof u %d\n", sizeof(u));
结构s
测得大小为16,而联合u
测得大小为8。
对于结构来说,char占用1字节,short占用2个字节。long long占用8字节。如果它们相邻紧密排列,按理说会占用11个字节。
似乎两个结果都有些奇怪。让我们将其成员的地址打印出来,详细地分析一下,它们的内存排布情况。
struct {
char c;
short s;
long long ll;
}s;
union {
char c;
short s;
long long ll;
}u;
printf("&s.c %d \n", &s.c);
printf("&s.s %d \n", &s.s);
printf("&s.ll %d \n\n", &s.ll);
printf("&u.c %d \n", &u.c);
printf("&u.s %d \n", &u.s);
printf("&u.ll %d \n", &u.ll);
结构s
的成员c
的首地址为8649904。
结构s
的成员s
的首地址为8649906。
结构s
的成员ll
的首地址为8649912。
根据地址,我们画出了结构s
各个成员的内存排布情况。char
与short
只留空了一个字节,而short
与long long
之间留空了4个字节。
这种现象被称为内存对齐,虽然会浪费一些内存空间,对齐后的数据能够被更快的访问。
内存对齐有一套规则,这里我们并不展开讨论结构中的成员是如何对齐的了。我们接着往下看,看看联合中的成员的内存排布情况。
联合u
的成员c
的首地址为8649896。
联合u
的成员s
的首地址为8649896。
联合u
的成员ll
的首地址为8649896。
似乎联合中成员的首地址是重叠的。
没错,联合中的成员首地址是重叠的,这意味着联合的大小为联合中最大成员的大小。
接下来,我们进一步研究联合的性质。