• C primer plus学习笔记 —— 9、联合&枚举&typdef


    联合

    联合能在同一存储空间存储不同类型的数据(和struct不同不是同时存储)。
    一次只能存储一种类型的值。他的主要目的是节省空间。

    声明

    形式同struct相同:但是含义不同.
    struct表示这个结构体可以存储一个int,一个double和一个char
    但是union表示他只能存储一个int,或者一个double或者一个char

    struct hold1{
    	int digit;
    	double bigfl;
    	char letter;
    };
    union hold{
    	int digit;
    	double bigfl;
    	char letter;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    定义

    union hold fit; //定义一个fit变量
    union hold save[10]; //顶一个save数组
    union hold *pu; //指针
    
    • 1
    • 2
    • 3
    1. 定义变量,编译器会分配足够的空间,这里union的三个成员最大的是double,8字节,所以编译器会给fit分配8字节内存。
    2. 创建一个数组,内含10个元素,每个元素都是union类型并占8字节大小。
    3. 该指针变量存储一个hold类型地址

    初始化

    union hold{
    	int digit;
    	double bigfl;
    	char letter;
    };
    
    union hold a = {88}; //初始化,digit赋值
    union hold b = {.bigfl = 118.2}; //指定初始化
    
    //声明一个,并赋值
    union hold orig;
    orig.letter = '4';
    //可以用另一个联合来给一个联合初始化
    union hold c = orig;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    使用联合

    union hold fit;
    fit.digit = 23; //23存储在联合中,此时联合占4字节
    fit.bigfl = 2.0; //清除digit,并把2.0存储在bigfl中,占8字节
    fit.letter = 'h'; //清除bigfl,并把h存储在letter中,此时占1字节
    
    • 1
    • 2
    • 3
    • 4

    union一次只能存储一个值,即使有足够空间,也不能同时存储两个类型的值,所以在使用的时候要注意当前在union中存储的是哪个值。

    union hold{
    	int digit;
    	double bigfl;
    	char letter;
    };
    
    int main(void)
    {
        union hold a;
        a.digit = 899;
        printf("%d, %f, %c \n", a.digit, a.bigfl, a.letter); //899, 0.000000, � 
        a.bigfl = 445.56;
        printf("%d, %f, %c \n", a.digit, a.bigfl, a.letter); //-1030792151, 445.560000, ) 
        double dng = a.bigfl*4.5;
        printf("%f", dng);
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    上面这个例子我们可以看到,当我们给a.bigfl赋值的时候,a.digit的值被修改了,所以如果这时我们还要使用a.digit就不是我们想要的值了。

    匿名union

    struct owner {
    	char c[12];
    };
    struct outer {
    	char cc[78];
    };
    struct car_user {
    	char rt[34];
    	int status;
    	union {
    		struct owner owncar; //匿名联合中的变量
    		struct outer ocar;
    	};
    };
    
    struct car_user flit;
    flit.owncar.c;
    flit.ocar.cc;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    这时我们可以看到struct car_user中使用了一个匿名联合,我们可以这样使用他。

    枚举

    枚举类型目的是提高程序可读性。
    使用enum关键字来表示整型常量。使整数看起来更直观。

    enum spectrum {
    	red, orange, yellow, green, blue, violet
    };
    
    enum spcturm color;
    color = blue;
    color = 4;
    int c = blue;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    上面这个示例中,声明创建了一个名为spctrum的枚举。其中red,orange这些叫做枚举符。他们都是int类型。
    然后我们定义一个变量,color,他的值可以是red, orange, yellow.
    默认情况下枚举列表中的值从0开始被赋值,上面分别被赋值0~5.
    还可以给枚举常量赋值

    enum feline {
    	cat,      //0
    	lynx = 10,//10
    	puma, 	// 11	
    	tiger	//12	
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    因为color就是整型,我们可以把他放到for循环中使用。

    enum spectrum {red, orange, yellow, green, blue, violet};
    int main(void)
    {
        char choice[LEN];
        enum spectrum color;
        for (color = red; color <= violet; color++)
         {
         }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    typedef

    typedef用于为某一类型自定义名称。
    他与#define类似,但是有以下不同:

    • typdef由编译器解释,而不是预处理器
    • typedef只能用于类型的自定义名称,而不能给值进行重命名

    使用

    typedef unsigned char BYTE; //把unsigned char 重新自定义名称为BYTE
    
    BYTE x; //声明一个char变量,此句同 unsigned char x;
    
    • 1
    • 2
    • 3

    也可以使用#define来定义
    比如使用

    #define BYTE unsinged char
    
    • 1

    他和上面typedef一样。

    和define区别

    1. 可以使用其他类型说明符对宏类型名进行扩展,但对 typedef 所定义的类型名却不能这样做
    #define INTERGE int
    unsigned INTERGE n;  //没问题
    
    typedef int INTERGE;
    unsigned INTERGE n;  //错误,不能在 INTERGE 前面添加 unsigned
    
    • 1
    • 2
    • 3
    • 4
    • 5
    1. 连续定义区别
      但是我们看另一个定义
    typedef char * STRING
    #define char * STRING2
    
    STRING name, sign; //相当于char *name, char *sign;
    STRING2 name, sign; //相当于char *name, sign.
    
    • 1
    • 2
    • 3
    • 4
    • 5

    看上面对比,发现这样声明则#define在某些情况下起不到我们预期的作用。

    用于数组

    http://m.biancheng.net/view/2040.html

    typedef char ARRAY20[20];
    
    //下面两个声明相同
    ARRAY20 a1, a2, s1, s2;
    char a1[20], a2[20], s1[20], s2[20];
    
    • 1
    • 2
    • 3
    • 4
    • 5

    这里表示ARRAY20是char[20]的别名,表示一个char类型大小为20的数组。

    用于指针

    typedef int (*PTR_TO_ARR)[4];
    
    PTR_TO_ARR p1, p2;
    
    • 1
    • 2
    • 3

    表示 PTR_TO_ARR 是类型int * [4]的别名,它是一个二维数组指针类型.

    用于结构体

    typedef struct complex {
    	float real;
    	float imag;
    } COMPLEX;
    
    COMPLEX a; //定义变量a,等同于 stuct complex a;
    
    struct book {       
        char title[MAXTITL];
        char author[MAXAUTL];
        float value;
    } lib;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    这里和结构体就不同类,结构体的下面lib是创建一个变量,而这里的COMPLEX是一个类型别名,并未创建变量。
    可以看到使用COMPLEX可以方便的创建一个struct complex类型。

  • 相关阅读:
    heic图片如何转为jpg格式
    springboot高校学生健康档案管理系统java ssm
    PAT甲级 1072 Gas Station(30) (Dijkstrla)
    docker容器保持运行不退出
    C语言第入门——第十六课
    汇凯金业:黄金期货交易时间规则
    JSP命令标签 静态包含/动态包含
    从零开始学习CAN总线协议(一)
    Golang 动态脚本调研
    Java类变量和类方法(static)
  • 原文地址:https://blog.csdn.net/chongbin007/article/details/126083536