1. enum枚举

1.1. C enum

enum是C语言中的一个关键字,enum叫枚举数据类型,枚举类型可以让我们的程序使用一些固定长度和固定数值的变量值范围。枚举型是预处理指令#define的替代,枚举和宏其实非常类似,宏在预处理阶段将名字替换成对应的值,枚举在编译阶段将名字替换成对应的值。

  • 格式

    1
    2
    3
    4
    5
    6
    enum typename{
    valuaname1,
    valuename2,
    valuename3,
    ...
    }

    typeName是枚举类型的名字,花括号里面的元素(枚举成员)是常量而不是变量,因为枚举成员的是常量,所以不能对它们赋值,只能将它们的值赋给其他的变量

  • 注意
    1. 枚举型是一个集合,集合中的元素(枚举成员)是一些命名的整型常量,元素之间用逗号,隔开。
    2. 第一个枚举成员的默认值为整型的0,后续枚举成员的值在前一个成员上加1。在当前值没有赋值的情况下,枚举类型的当前值总是前一个值+1。
    3. 可以人为设定枚举成员的值,从而自定义某个范围内的整数。
    4. 类型定义以分号;结束。
  • 枚举变量的定义
    1. 先定义枚举类型,再定义枚举变量
      1
      2
      3
      4
      5
      enum DAY
      {
      ...
      };
      enum DAY day1;
    2. 定义枚举类型的同时定义枚举变量
      1
      2
      3
      4
      enum DAY
      {
      ...
      }day1;
    3. 省略枚举名称,直接定义枚举变量
      1
      2
      3
      4
      enum
      {
      ...
      }day1;
    4. 使用typedef
      1
      2
      3
      4
      5
      typedef enum 
      {
      ...
      }DAY;
      DAY day1;
  • 使用枚举类型的变量
    1. 枚举成员是常量,不能对它们赋值,只能将它们的值赋给其他的变量。他们只能在等号左边。
    2. 允许非枚举值赋值给枚举类型的变量(不是枚举成员), 允许其他枚举类型的值赋值给当前枚举类型。
      1. 不同枚举 类型的枚举值可以直接比较。
      2. 枚举值具有外层作用域,容易造成名字冲突,即不能定义与枚举成员同名的变量(无论什么类型)。
  • 枚举和宏其实非常类似:宏在预处理阶段将名字替换成对应的值,枚举在编译阶段将名字替换成对应的值。我们可以将枚举理解为编译阶段的宏。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    #include <stdio.h>

    int main()
    {
    enum Week { Mon, Tue, Wed, Thi, Fri, Sat, Sun };
    enum Other { One, Two, Three };
    enum Week week = Mon;

    // 1. 允许非枚举值赋值给枚举类型, 允许其他枚举类型的值赋值给当前枚举类型
    week = 100; //ok
    week = One; //ok

    // 2. 枚举值具有外层作用域,容易造成名字冲突
    //int One = 100; //error //错误 C2365 “One” : 重定义;以前的定义是“枚举数”

    // 3. 不同类型的枚举值可以直接比较
    if (week == One)
    {
    printf("equal\n"); //equal
    }

    return 0;
    }

    1.2. C++ enum

    基本与C enum一致
    但是在使用时有区别:

  1. C++ 只能允许赋值枚举值(枚举成员),且不允许其他枚举类型的值赋值给当前枚举类型
  2. 不同的两个枚举类型,若含有相同枚举元素,则会冲突

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    #include <iostream>
    using namespace std;

    int main()
    {
    enum Week { Mon, Tue, Wed, Thi, Fri, Sat, Sun };
    enum Other { One, Two, Three };
    enum Week week = Mon; //警告 C26812 枚举类型“main::__l2::Week”未设定范围。相比于 "enum",首选 "enum class" (Enum.3)。


    // 1. C++ 只能允许赋值枚举值
    // week = 100; //error
    // week = One; //error

    // 2. 枚举元素会暴露在外部作用域,不同的两个枚举类型,若含有相同枚举元素,则会冲突
    //enum OtherWeek { Mon }; //error,重定义,以前的定义是枚举数

    // 3. C++ 只允许同枚举类型值之间比较(作者说得貌似不对,能够比较!)
    enum E1 { A, B };
    enum E2 { C, D };
    cout << (E1::B == E2::D ? "相等" : "不相等") << endl; //相等

    return 0;
    }

    1.3. enum class(强枚举类型)(C++11新特性)

    强枚举类型禁止不同枚举类型之间进行比较。
    强枚举类型不会将枚举元素暴露在外部作用域

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    #include <iostream>
    using namespace std;
    int main()
    {
    enum class E1 { A = 1, B = 2 };
    enum class E2 { A = 1, C = 2 };

    // 1. 强枚举类型不会将枚举元素暴露在外部作用域
    cout << (int)(E1::A) << endl; //1
    int A = 100;

    // 2. 不相关的两个枚举类型不能直接比较,编译报错
    //cout << (E1::B == E2::C ? "相等" : "不相等") << endl; //error //E0349 没有与这些操作数匹配的 "==" 运算符
    //cout << (E1::B == 2 ? "相等" : "不相等") << endl; //error E0349 没有与这些操作数匹配的 "==" 运算符

    return 0;
    }

2. struct

  1. 先定义结构体,再定义结构体变量
    1
    2
    3
    4
    5
    struct 结构体名
    {
    ...
    };
    struct 结构体名 变量名;
  2. 定义结构体时同时定义结构体变量
    1
    2
    3
    4
    struct 结构体名
    {
    ...
    }变量名;
  3. 第2种,如果后续不再使用结构体定义变量,也可以省略结构体名。
  4. 使用typedef(推荐)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    typedef struct
    {
    ...
    } 结构体别名;
    结构体名 变量名;
    // 或者
    typedef struct 结构体名
    {
    ...
    } 结构体别名;
    结构体别名 变量名;
  5. 结构体变量初始化
    1
    2
    3
    4
    5
    struct student
    {
    char name[50];
    int id;
    } charon = {"charon", 666};