C语言 day18
结构体
位段
- 信息在计算的存取长度一般以字节为单位;
- 有事储存一个信息不必用一个字节或多个字节
- 例如:真或假:用0或1,只需一位即可.
怎样向一个字节的一个或几个二进制位赋值和改变他的值呢
- 利用前面学过的为运算符:
<< >> & | ~ ^
- 结构体定义位段,利用位段可以减少存储空间并简化位的操作
C语言允许一个结构体中以位为单位来指定其成员所占内存长度,以位为单位的成员为“位段”或称“位域”。
注意:位段一般用的是unsigned int
或unsigned char
案例1:
- 位域的存储
- 当相邻成员的类型相同时,如果它们的位宽之和小于类型的 sizeof 大小,那么后面的成员紧邻前一个成员存储,直到不能容纳为止;如果它们的位宽之和大于类型的 sizeof 大小,那么后面的成员将从新的存储单元开始,其偏移量为类型大小的整数倍。
1 |
|
分析:
在 GCC 下的运行结果为 1,三个成员挨着存储;在 VC/VS 下的运行结果为 8(为什么不是5?见上篇文章结构体内存对齐),三个成员按照各自的类型存储(与不指定位宽时的存储方式相同)。
- 如果成员之间穿插着非位域成员,那么不会进行压缩。
1 | struct data1{ |
在各个编译器下 sizeof 的结果都是 12。
案例2:
- 位段不能取地址:系统给内存中一个字节分配一个地址,位没有一个字节,没有地址结果:
1
2
3
4
5
6
7
8
9
10
struct data1{
unsigned char a:2;
unsigned int b:2;
};
int main(int argc,char *argv[]){
struct data1 z;
printf("%d\n",&z.a);
return 0;
}
编译器会报错,不能对位的变量取地址
案例3:
- 位段的赋值不要超过位段的大小,运行结果:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
struct data1{
unsigned char a:2;
unsigned char b:2;
unsigned char c:2;
};
int main(int argc,char *argv[]){
struct data1 z;
z.a=3;//11
z.b=4;//100
z.c=5;//101
printf("%#x\n",z.a);
printf("%#x\n",z.b);
printf("%#x\n",z.c);
return 0;
}
分析:如果超过位段的大小,则会取后面的值,前面的被截去了,显然这个没有意义的
案例4:
- 无意义的位段 :2占有两位
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
struct data1{
unsigned char a:2;
unsigned char :5;
unsigned char c:2;
};
struct data2{
unsigned char a:2;
unsigned char :4;
unsigned char c:2;
};
int main(int argc,char *argv[]){
printf("%d\n",sizeof(struct data1));//2
struct data2 z;
memset(&z,0,sizeof(z));
//1100 0010 0xc2
z.a=2;//10
z.c=3;//11
unsigned char *p=&z;
printf("%#x\n",*p);
return 0;
}
运行结果:
案例5:
- 另起一个位段 :0 使下一个位段从下一个存储单元开始存放
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
struct data1{
unsigned char a:2;
unsigned char :0;
};
struct data2{
unsigned char a:2;
unsigned char :0;
unsigned char c:2;
};
struct data3{
unsigned char a:2;
//unsigned char :0;
unsigned char c:2;
};
int main(int argc,char *argv[]){
printf("%d\n",sizeof(struct data1));
printf("%d\n",sizeof(struct data2));
printf("%d\n",sizeof(struct data3));
return 0;
}
运行结果:
注意:不会立马生效。是从下一个位段开始,在下一个存储单元存放,所以struct data1
的字节数仍是1