1、struct位字段
位字段是C语言 struct 的一种特殊数据结构,它的属性(这里称为字段)由二进制位组成,适合操作二进制数据。每个属性的取值只有整数且不会出现负值,故数据类型为 unsigned int。
位字段结构体的声明格式举例:
typedef struct
{
unsigned int a : 1; //a:1表示这个属性a占1个二进制位
unsigned int b : 1;
unsigned int c : 1;
unsigned int d : 1;
} binStruct;
上面这个例子,a、b、c、d四个字段共计占了四个二进制位,但我们用 sizeof 计算位字段结构体的大小时,得到的却是4个字节。4个位与4个字节差很多啊?原因是C语言在存储位字段结构时,是按照int类型占用的字节数进行存储的,一个位字段结构如不超过int字节数则其占用的空间就是1个int类型所占字节数,所以上面的例子显示的大小是4个字节。
但当一个位字段结构超过int字节数,且正好有一个字段跨在两个int字节之间,这样的情况程序是会出问题的,怎样处理呢?可以在跨字节字段的前面加上一个有类型、无字段名、占位为0的字段(unsigned int :0),这个字段属占位字段,可以把跨字节字段挤到下一个int字节中;这种情况再用sizeof计算位字段结构的大小,就会是8个字节。总之,一个字段所在位置绝不能跨在两个int字节之间。
位字段的优点就是节省内存空间,比如RGB颜色,就是r、g、b三组0~255之间的数值组合而成的,白色(255,255,255)、红色(255,0,0),灰
色(211,211,211),为储存这些数据,我们定义一个位字段:
typedef struct
{
unsigned int r : 8;
unsigned int g : 8;
unsigned int b : 8;
} Color;
用Color这个位字段结构存储rgb颜色值,三组数只用了4个字节,实际4个字节还没用满,剩余的部分还可以另做它用。
2、struct弹性数组成员
数组在使用前有时不能确定组成员的准确数量。如果声明数组的时候,宽打窄用给一个很大的数字,会造成浪费内存空间。为此,C语言提供了一个利用结构体解决的方法,叫做弹性数组成员。具体做法是,可以定义一个struct结构,里面正常的成员该怎样设置就怎样设置,和弹性数组成员有关的是两个:a.记录弹性数组成员个数的 int 变量;b. char、int或其它类型 (含自定义结构体) 的弹性数组。举例:
typedef struct
{
int lenth;
char myChar[];
} myCharArr;
上例中,myCharArr结构体有两个属性。lenth属性用来记录数组myChar的长度,myChar是一个字符数组,但是没有给出成员数量。myChar数组准确成员数,可以在为myCharArr初始化时确定。再举一个int型完整例子进一步说明使用方法:
//位字段结构体
typedef struct
{
unsigned int a : 1; //a:1表示这个属性a占1个二进制位
unsigned int b : 1;
unsigned int c : 1;
unsigned int d : 1;
} binStruct;
//带有弹性数组成员的结构体
typedef struct
{
int lenth;
int myInt[];
} myIntArr;
#include<stdio.h>
#include<stdlib.h> //malloc需用
int main(void)
{
//位字段结构的字节数
printf("binStruct size=%lld\n", sizeof(binStruct)); //运行结果:binStruct size=4
//位字段结构体最小为一个int类型所占字节数
//弹性数组成员
int n = 10;
//声明 (假定现在要使用一个10个成员数组)
myIntArr* myintarr = malloc(sizeof(myIntArr) + n * sizeof(int));
if (myintarr == NULL) return 0;
//赋值
myintarr->lenth = n;
for (int i = 0; i < myintarr->lenth; i++)
{
myintarr->myInt[i] = i * 100+100;
}
//遍历
for (int i=0;i<myintarr->lenth;i++)
{
printf("myInt[%i] %i\n", i,myintarr->myInt[i]);//运行结果:略
}
getchar();
return 0;
}