C语言从头学39——结构体位字段、弹性数组成员

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;
}

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值