看过《中国象棋将帅问题》的朋友都知道,这个问题的玄奥就在于“只能使用一个字节存储变量”,没有规定变量个数,所以对于这一个字节的处理就构成了这个问题的编程之美。
作者给出了三个不同类型的算法,忘记的朋友马上翻书重温一下,这三种算法各有特色,这里就不一一列举,写这篇博文主要是想和大家分享一下第三种算法的相关知识。
第三种算法的代码主体:
struct {
unsigned char a:4;
unsigned char b:4;
} i;
for (i.a = 1; i.a <= 9; i.a++)
for (i.b = 1; i.b <= 9; i.b++)
if (i.a % 3 != i.b % 3)
printf ("A = %d, B = %d\n", i.a, i.b);
看到这里大家一定会注意到,对,他用到了位域结构体,在微软的题目中,位域从来不是稀客。
有些时候,我们所使用的变量不用占用整个字节,只需要几个比特就可以,那么你就可以尝试使用位域,下面是关于位域的一些规则:
- 如果相邻位域字段的类型相同,而且位宽之和小于该类型的宽度,那么后面的字段就会接着前一字段连续存储,直到超出类型宽度。
- 如果相邻位域字段的类型相同,但是位宽之和大于该类型的宽度,那么超出的部分将从新的地址单元开始存储。
- 如果相邻位域字段的类型不同,处理模式根据不同的编译器有不同的表现。
- 如果位域字段中间有非位域字段,则从连续相邻的位域字段开始压缩。
- 压缩后的大小为该类型宽度的整数倍。
- 没有起名的位域为空位域,自动以0填充,只能用作调整位置,不能存储数据。
- 连续存储数据,遵从由低到高的原则,先填充低位再填充高位。
实例:
struct {
unsigned char a:4;//相邻为非位域字段b,不压缩,占sizeof(int)=4字节(按照结构体“字节对齐”规则)
unsigned int b; //占4字节
unsigned char c:4;
unsigned char d:4;
unsigned char e:4;
unsigned char f:4;
unsigned char g:4;//c,d,e,f,g为连续位域字段,使用压缩,连续存储,实际占20bits,字节对齐,占4字节。
} i;//所以sizeof(i)=12
这里要注意的是,不是c,d填充一个char的大小后,然后作为一个char去和int对齐,而是c,d,e,f,g整个整体去和int对齐。