C语言进阶——自定义类型详解(下)——位段、枚举、联合详解

目录

一、位段

1、定义:

2、内存分配:

3、跨平台问题:

4、应用:

二、枚举

1、定义:

2、优点:

3、使用:

三、联合(共用体)

1、定义:

2、特点:

3、大小的计算:


C语言进阶——自定义类型详解(下)——位段、枚举、联合详解_第1张图片

 

一、位段

1、定义:

位段是通过结构体来实现的,位段的声明和结构是类似的,但是还是有两个不同之处:

(1). 位段的成员必须是 int、unsigned int 或signed int 。
(2). 位段的成员名后边有一个冒号和一个数字。

例: A就是一个位段类型,那位段A的大小是多少?

struct A
{
    int _a:2;
    int _b:5;
    int _c:10;
    int _d:30;
};

int main()
{
    printf("%d\n", sizeof(struct A));
}

C语言进阶——自定义类型详解(下)——位段、枚举、联合详解_第2张图片 

如图我们得到的结果是8,答案是不是出乎预料?那结果是如何得出的呢?那就要看下面的内存分配了。

 

2、内存分配:

(1). 位段的成员可以是 int unsigned int signed int 或者是 char (属于整形家族)类型
(2). 位段的空间上是按照需要以4个字节( int )或者1个字节( char )的方式来开辟的。
(3). 位段涉及很多不确定因素,位段是不跨平台的,注重可移植的程序应该避免使用位段。

 例:

struct S
{
    char a:3;
    char b:4;
    char c:5;
    char d:4;
};

struct S s = {0};
s.a = 10;
s.b = 12;
s.c = 3;
s.d = 4;

 C语言进阶——自定义类型详解(下)——位段、枚举、联合详解_第3张图片

【1】、a=10->1010,只分配给a,3个比特位,截取010放到第一个字节中(从低位开始放)。【2】、b=12->1100,第一个字节还剩5个比特位,空间足够,放在第一个字节。
【3】、c=3->11,因为分给五个比特位,所以c=00011,第一个字节空间不够,所以放到第二个字节中。                                                                                                                                          【4】、d=4->100,因为分给四个比特位,所以d=0100,第二个字节空间不够,所以放在第三个字节中。

 

3、跨平台问题:

(1). int 位段被当成有符号数还是无符号数是不确定的。
(2). 位段中最大位的数目不能确定。(16位机器最大16,32位机器最大32,写成27,在16位机器会出问题)。
(3). 位段中的成员在内存中从左向右分配,还是从右向左分配标准尚未定义。
(4). 当一个结构包含两个位段,第二个位段成员比较大,无法容纳于第一个位段剩余的位时,是舍弃剩余的位还是利用,这是不确定的。

因此,相比于结构体,位段不仅可以达到相同的效果,而且还可以更好的节省空间,但还是存在着跨平台的问题。

 

4、应用:

C语言进阶——自定义类型详解(下)——位段、枚举、联合详解_第4张图片

二、枚举

1、定义:

顾名思义就是 一 一 列举,把可能的取值 一 一 列举出来。
比如我们现实生活中:从周一到周日,就可以通过枚举来显示。

例:

enum Day//星期
{
    Mon,
    Tues,
    Wed,
    Thur,
    Fri,
    Sat,
    Sun
};

enum Sex//性别
{
    MALE,
    FEMALE,
    SECRET
};

enum Color//颜色
{
    RED,
    GREEN,
    BLUE
}

 以上定义的enum Day,enum Sex,enum Color都是枚举类型,{ }中的内容是枚举类型可能取值,也叫做枚举常量。

这些可能取值都是有值的,默认从0开始,依次递增1,但是在定义的时候也可以赋初值。

例:

enum Color
{
    RED=1;
    GREEN=2;
    BLUE=4;
};

 

2、优点:

以上的常量定义我们可以通过#define来定义,为什么还要使用枚举呢?

下面便是枚举的优点:

(1). 增加代码的可读性和可维护性
(2). 和#define定义的标识符比较枚举有类型检查,更加严谨。
(3). 防止了命名污染(封装)
(4). 便于调试
(5). 使用方便,一次可以定义多个常量

3、使用:

enum Color
{
    RED=1,
    GREEN=2,
    BLUE=4
};
int main()
{
    enum Color clr = GREEN;    //只能拿枚举常量给枚举变量赋值,才不会出现类型的差异!!!
    printf("%d",clr);
}

三、联合(共用体)

1、定义:

联合体也是一种特殊的自定义类型,这种类型定义的变量也包含一系列的成员,特征是这些成员公用同一块空间,所以联合也叫共用体。

例:

//联合类型的声明
union Un
{
    char c;
    int i;
};
int main()
{
    //联合变量的定义
    union Un un;
    //计算变量大小
    printf("%d\n", sizeof(un));
}

 C语言进阶——自定义类型详解(下)——位段、枚举、联合详解_第5张图片

 

2、特点:

联合的成员是共用同一块内存空间的,这样一个联合变量的大小,至少是最大成员的大小,因为联合至少得有能力保存最大的那个成员。

例:

union Un
{
    int i;
    char c;
};
int main()
{
    union Un un;
    // 下面输出的结果是一样的吗?
    printf("%d\n", &(un.i));
    printf("%d\n", &(un.c));

    //下面输出的结果是什么?
    un.i = 0x11223344;
    un.c = 0x55;
    printf("%x\n", un.i);
}

C语言进阶——自定义类型详解(下)——位段、枚举、联合详解_第6张图片

 

3、大小的计算:

(1). 联合的大小至少是最大成员的大小。
(2). 当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍。

union Un1
{
    char c[5];    //1  5  
    int i;        //4  4  
};
union Un2
{
    short c[7];    //2  7
    int i;         //4  4
};
int main()
{
    //下面输出的结果是什么?
    printf("%d\n", sizeof(union Un1));
    printf("%d\n", sizeof(union Un2));
}

C语言进阶——自定义类型详解(下)——位段、枚举、联合详解_第7张图片

 

C语言进阶——自定义类型详解(下)——位段、枚举、联合详解_第8张图片

 

你可能感兴趣的:(C语言进阶知识点,c语言)