《王道程序员求职宝典》笔记 - 第3章 结构体、共用体与枚举
by 宋强
struct和class在c++中的不同 struct的元素默认为public,而class的元素默认为private,其他的并没有不同。
快速判断是大端还是小端 下面两个函数都是一个道理,大端就是高字节存高地址,小端就是高字节存低地址。
#define BIG_ENDIAN 0
#define LITTLE_ENDIAN 1
int TestByteOrder() {
short int word = 0x1;
char *byte = (char *)word;
return (byte[0] ? LITTLE_ENDIAN : BIG_ENDIAN);
}
int testByteOrder() {
Union testUnion {
int i;
unsigned char[]
}testUnit;
testUnit.i = 0x1;
return (byte[0] ? LITTLE_ENDIAN: BIG_ENDIAN);
}
C语言参数的入栈顺序 C语言参数入栈顺序为从右至左,这是由于C语言需要支持不定数目参数决定的。
C语言的栈 栈顶为低地址,栈底为高地址。
位域数据存放的基本规则
- 低字节都放在低地址。
- 大端模式先为MSB配空间,小段模式先为LSB分配空间。
- 大端模式高地址存放高bit(每个bit域中),小段模式相反。
例,如何推算大小端模式下位域在内存中的分布:
struct { short bit1:4; short bit2:9; short bit3:3; };第一步,先按大端模式推算,内存中即为:
| bit1(4位,$a_0a_1a_2a_3$) | bit2(高4位$a_5a_6a_7a_8$) | bit2(低5位$a_0a_1a_2a_3a_4$) | bit3(3位$a_0a_1a_2$) |
高4位低5位分布是遵循规则2,内部分布遵循规则3。
第二步,开始计算小端,按照规则3,将每个bit域中的内部序列分布调换,变为
| bit1($a_3a_2a_1a_0$) | bit2($a_8a_7a_6a_5$) | bit2($a_4a_3a_2a_1a_0$) | bit3($a_2a_1a_0$) |
第三步,按照规则2,小端模式会先为LSB元素分配空间,所以bit2中变为先分配低4位,再分配高5位
| bit1($a_3a_2a_1a_0$) | bit2($a_3a_2a_1a_0$) | bit2($a_8a_7a_6a_5a_4$) | bit3($a_2a_1a_0$) |
第四步,交换每个字节内部cell顺序,例如第一个字节就是交换bit1 4位和bit2高四位, 变为
| bit2($a_3a_2a_1a_0$) | bit1($a_3a_2a_1a_0$) | bit3($a_2a_1a_0$) | bit2($a_8a_7a_6a_5a_4$) |
可使用$P_{44}$例5验证。
sizeof
- sizeof是在编译时计算的。
- 是一个u单目运算符,并不属于函数。
- 可在常量表达式中使用,并且作为常量使用。
- sizeof中可以放表达式,但是sizeof只是针对结果大小返回结果,并不会对表达式进行计算,函数也不会执行。
- sizeof用于类型时必须加括号,比如sizeof(int);,但是用于变量时可以不加括号,比如sizeof a;就是正确的。
- 函数名,不能确定类型的表达式和位域成员不能计算sizeof值。
- sizeof可用于计算数组大小,但当数组作为参数在c++中传递时,传递的其实是指针,所以这个时候sizeof得到的是指针的大小。比如:
void fun1 (char a1[3]) {
int c1 = sizeof(a1); // c1 = 4
}
void fun2 (char a2[]) {
int c2 =sizeof (a2); // c2 = 4
}
struct空间占用计算规则
- 整体所占空间是所占空间最大的成员的空间的整数倍。
- 每个成员前面分配的大小需是这个成员自身大小的整数倍,但Linux+gcc下只要前面是4的整数倍就可以。
- 数组在结构体中按照连续的单个元素来看待。
如果结构体中存在结构体的话
- 整体所占空间是父子结构体中所占空间最大的成员的空间的整数倍。
- 到子结构体时,前面分配的大小需是子结构体中所占空间最大的成员的空间的整数倍。但Linux+gcc下也是只是前面是4的倍数就行。
含位域空间的struct空间占用计算规则
- 若相邻位域字段类型相同,且位宽之和小于sizeof(类型)大小,将紧邻前一个位域存储。
- 若相邻位域字段类型相同,且位宽之和大于sizeof(类型)大小,将在偏移sizeof(类型)的整数倍的新空间存储。
- 若相邻位域字段类型不同,具体行为取决于编译器,VC6不压缩,而Dev-C++和gcc压缩。
使用#pragma pack控制空间分配
- 使用伪指令#pragma pack(n):这之后按照min(sizeof(类型), n)字节对齐。
- 使用伪指令#pragma pack():取消之前的#pragma pack的作用。
空结构体的大小为1。
Union的空间计算规则
- 整体所占空间是占空间最大元素所占空间的整数倍。
- 大小为先计算各个的sizeof()之后按照1.进行对齐。
Enum的空间计算规则 大小都为4,本质上是一个存储int的空间。
习题
待补充。
tags: c++ - 笔试 - 笔记