【从0开始跟Chat老师学嵌入式 03】C语言入门 - 枚举类型、派生数据类型、用户定义数据类型

小白:C语言枚举类型

Chat老师:

在 C 语言中,枚举类型(enum)是一种用户定义的数据类型,它由一组命名的整数常量组成。枚举类型提供了一种为整数值赋予有意义的名称的方式,使代码更加清晰和可读。

定义枚举类型

枚举类型的定义使用 enum 关键字,语法如下:

enum 枚举名 {
    枚举常量1,
    枚举常量2,
    ...
    枚举常量n
};

示例

以下是一个定义颜色的枚举类型示例:

#include <stdio.h>

enum Color {
    RED,
    GREEN,
    BLUE
};

int main() {
    enum Color favoriteColor;

    favoriteColor = GREEN;

    printf("Favorite color: %d\n", favoriteColor);

    return 0;
}

在这个例子中,enum Color 定义了一个枚举类型 Color,它包含三个枚举常量:RED, GREEN, 和 BLUE。默认情况下,RED 的值为 0GREEN 的值为 1BLUE 的值为 2

指定枚举常量的值

你可以显式地为枚举常量指定值。例如:

#include <stdio.h>

enum Color {
    RED = 1,
    GREEN = 3,
    BLUE = 5
};

int main() {
    enum Color favoriteColor;

    favoriteColor = BLUE;

    printf("Favorite color: %d\n", favoriteColor);

    return 0;
}

在这个例子中,RED 的值为 1GREEN 的值为 3BLUE 的值为 5

枚举的优点

  • 代码可读性:通过为整数值提供有意义的名称,代码更加容易理解。
  • 代码维护性:枚举类型使得代码更易于维护。如果需要添加或修改值,只需更新枚举定义。
  • 避免魔法数字:使用枚举可以避免代码中出现“魔法数字”,即没有明确含义的数字。

示例:更复杂的枚举类型

以下是一个更复杂的示例,展示如何使用枚举类型:

#include <stdio.h>

enum Day {
    SUNDAY,
    MONDAY,
    TUESDAY,
    WEDNESDAY,
    THURSDAY,
    FRIDAY,
    SATURDAY
};

void printDay(enum Day day) {
    switch (day) {
        case SUNDAY:    printf("Sunday\n"); break;
        case MONDAY:    printf("Monday\n"); break;
        case TUESDAY:   printf("Tuesday\n"); break;
        case WEDNESDAY: printf("Wednesday\n"); break;
        case THURSDAY:  printf("Thursday\n"); break;
        case FRIDAY:    printf("Friday\n"); break;
        case SATURDAY:  printf("Saturday\n"); break;
        default:        printf("Invalid day\n"); break;
    }
}

int main() {
    enum Day today = WEDNESDAY;
    printDay(today);
    return 0;
}

在这个例子中,定义了一个表示星期几的枚举类型 Day,并编写了一个函数 printDay,根据枚举值打印相应的星期几。

小结

  • 枚举类型提供了一种为整数值赋予有意义名称的方法。
  • 枚举类型定义使用 enum 关键字,并包含一组命名的整数常量。
  • 可以显式地为枚举常量指定值。
  • 枚举类型提高了代码的可读性和可维护性。

=========================================================================

小白:C语言中除了基本数据类型,枚举数据类型,还有哪些数据类型

Chat老师:

在 C 语言中,除了基本数据类型和枚举数据类型,还有几种其他类型的数据类型,主要包括派生数据类型和用户定义数据类型。这些类型提供了更多的灵活性和功能性,以便开发者能够更好地组织和管理数据。

派生数据类型

  1. 数组(Array)

    • 用于存储相同类型元素的集合。
    • 例如:
      int numbers[10];  // 定义一个包含10个整数的数组
      char name[50];    // 定义一个包含50个字符的数组
      

  2. 指针(Pointer)

    • 存储另一个变量的内存地址。
    • 例如:
       
      int *ptr;    // 定义一个指向整数的指针
      char *str;   // 定义一个指向字符的指针
      

  3. 结构体(Struct)

    • 用于将不同类型的数据组合在一起。
    • 例如:
       
      struct Person {
          char name[50];
          int age;
          float height;
      };
      

  4. 共用体(Union)

    • 与结构体类似,但所有成员共享相同的内存位置。
    • 例如:
       
      union Data {
          int i;
          float f;
          char str[20];
      };
      

  5. 函数(Function)

    • 定义执行特定任务的代码块,可以返回值。
    • 例如:
       
      int add(int a, int b) {
          return a + b;
      }
      

用户定义数据类型

  1. 类型定义(typedef)
    • 用于为现有数据类型创建新名称,增加代码的可读性和维护性。
    • 例如:
      typedef unsigned long ulong;
      typedef struct Person {
          char name[50];
          int age;
          float height;
      } Person;
      

  2. 详细示例

    数组示例
    #include <stdio.h>
    
    int main() {
        int arr[5] = {1, 2, 3, 4, 5};
        for(int i = 0; i < 5; i++) {
            printf("%d ", arr[i]);
        }
        return 0;
    }
    

    指针示例

    #include <stdio.h>
    
    int main() {
        int num = 10;
        int *p = &num;
        printf("Value of num: %d\n", num);
        printf("Address of num: %p\n", p);
        printf("Value pointed by p: %d\n", *p);
        return 0;
    }
    

    结构体示例
    #include <stdio.h>
    
    struct Person {
        char name[50];
        int age;
        float height;
    };
    
    int main() {
        struct Person person1;
        person1.age = 30;
        person1.height = 5.9;
        strcpy(person1.name, "John Doe");
        
        printf("Name: %s\n", person1.name);
        printf("Age: %d\n", person1.age);
        printf("Height: %.2f\n", person1.height);
    
        return 0;
    }
    

    共用体示例
    #include <stdio.h>
    
    union Data {
        int i;
        float f;
        char str[20];
    };
    
    int main() {
        union Data data;
        data.i = 10;
        printf("data.i: %d\n", data.i);
    
        data.f = 220.5;
        printf("data.f: %.1f\n", data.f);
    
        strcpy(data.str, "C Programming");
        printf("data.str: %s\n", data.str);
    
        return 0;
    }
    

    类型定义示例
    #include <stdio.h>
    
    typedef struct {
        char name[50];
        int age;
        float height;
    } Person;
    
    int main() {
        Person person1;
        person1.age = 30;
        person1.height = 5.9;
        strcpy(person1.name, "Jane Doe");
        
        printf("Name: %s\n", person1.name);
        printf("Age: %d\n", person1.age);
        printf("Height: %.2f\n", person1.height);
    
        return 0;
    }
    

=========================================================================

小白:共用体与结构体类似,但所有成员共享相同的内存位置。这是什么意思

Chat老师:

在 C 语言中,结构体(struct)和共用体(union)都是用户定义的数据类型,用于将不同类型的数据组合在一起,但它们在内存分配和成员访问方面有显著的区别。

结构体(struct)

结构体的每个成员都有自己的内存位置,彼此独立,因此结构体的总大小是所有成员大小之和(加上任何必要的内存对齐)。例如:

#include <stdio.h>

struct ExampleStruct {
    int i;
    float f;
    char c;
};

int main() {
    struct ExampleStruct example;
    example.i = 42;
    example.f = 3.14;
    example.c = 'a';

    printf("example.i: %d\n", example.i);
    printf("example.f: %f\n", example.f);
    printf("example.c: %c\n", example.c);

    return 0;
}

在这个例子中,example.iexample.fexample.c 分别占用独立的内存空间。即使它们存储在同一个结构体实例中,它们之间没有内存重叠。

共用体(union)

共用体的所有成员共享相同的内存位置,因此共用体的总大小是其最大成员的大小。也就是说,在任一时刻,共用体只能存储一个成员的值。更改一个成员的值会覆盖其他成员的值。例如:

#include <stdio.h>

union ExampleUnion {
    int i;
    float f;
    char c;
};

int main() {
    union ExampleUnion example;
    example.i = 42;
    printf("example.i: %d\n", example.i);

    example.f = 3.14;
    printf("example.f: %f\n", example.f);

    example.c = 'a';
    printf("example.c: %c\n", example.c);

    // 尝试访问先前存储的值
    printf("After storing 'a' in example.c:\n");
    printf("example.i: %d\n", example.i);  // example.i 的值已被覆盖
    printf("example.f: %f\n", example.f);  // example.f 的值已被覆盖

    return 0;
}

在这个例子中,example.iexample.fexample.c 共享相同的内存位置:

  1. example.i 被赋值为 42 时,这个值占用了共用体的内存。
  2. example.f 被赋值为 3.14 时,42 被覆盖,因为 example.iexample.f 共享相同的内存位置。
  3. example.c 被赋值为 'a' 时,先前存储的 3.14 被覆盖。

因此,访问之前存储的值会得到不正确的结果,因为共用体的所有成员共享同一块内存。

内存布局

以下是结构体和共用体在内存中的布局示意图:

  • 结构体

    | int i | float f | char c |
    

  • 共用体:

    | int/float/char shared memory |
    

结构体和共用体的应用场景

  • 结构体:适用于需要同时存储和访问多个相关数据的情况。例如,表示一个人的信息(姓名、年龄、身高等)。
  • 共用体:适用于节省内存空间且在不同时间只需要存储一种类型数据的情况。例如,一个变量可能在不同情况下存储不同类型的值,或用于处理低级别的硬件或协议。

小结

  • 结构体:每个成员都有独立的内存位置,适合同时存储多个不同类型的数据。
  • 共用体:所有成员共享相同的内存位置,适合在不同时刻存储不同类型的数据。

理解这些差异有助于在合适的场景中正确使用结构体和共用体,从而提高代码的效率和可读性。

  • 14
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值