嵌入式Linux系统学习记录13

在 C 语言中,构造数据类型(也叫复合数据类型)包括结构体(struct)、共用体(union)和枚举类型(enum)。这些类型允许用户根据需求创建复杂的数据结构。下面是对每种类型的详细解析以及需要注意的细节和常见的陷阱。

1. 结构体(struct

结构体是 C 语言中最常用的复合数据类型,它允许将不同类型的数据(例如整数、字符数组等)组合在一起形成一个新类型。

定义:
struct Student {
    char name[50];    // 字符数组
    int age;          // 整数
    float score;      // 浮点数
};

使用:
struct Student s1;  // 定义一个结构体变量 s1
strcpy(s1.name, "Alice");
s1.age = 20;
s1.score = 88.5;

注意点:
struct Example {
    char a;   // 1 字节
    int b;    // 4 字节
};

虽然 ab 的总大小是 5 字节,但由于对齐要求,结构体的实际大小可能会是 8 字节(或者更大),具体取决于平台。
  • 结构体传递方式:结构体作为函数参数时,默认是按值传递的,意味着会创建结构体的副本。如果结构体比较大,传递的开销较大。可以使用指针来避免这个问题:

    void printStudent(struct Student *s)
    {
        printf("%s\n", s->name);
    }
    
    
  • 初始化:结构体可以在定义时进行初始化:

    struct Student s1 = {"Alice", 20, 88.5};

2. 共用体(union

共用体是一种特殊的结构体,允许多个成员共享同一段内存。所有成员共享相同的内存位置,但同一时间只能存储一个成员的值。

定义:

union Data { int i; float f; char str[20]; };

使用:

union Data data;
data.i = 10;            // 存储整数
data.f = 3.14;          // 存储浮点数(会覆盖 i 的值)
strcpy(data.str, "Hello");  // 存储字符串(会覆盖 f 的值)
 

注意点:
  • 内存共享:共用体的内存大小是其最大成员的大小。使用共用体时要特别注意,一次只能存储一个成员的值。如果你在 data 中存储了一个 int 值,接着存储一个 float,之前存储的 int 值会被覆盖。
  • 适用场景:共用体适用于某些场合需要节省内存的情况,尤其是在你知道一个时间点只会使用一个成员时。

3. 枚举类型(enum

枚举是用来定义一组命名的整数常量。通过枚举,你可以给常量赋予有意义的名字,从而使代码更加可读和易于理解。

定义:
enum Weekday {
    Monday = 1,    // 可以显式指定值
    Tuesday,
    Wednesday,
    Thursday,
    Friday,
    Saturday,
    Sunday
};
使用:
enum Weekday today;
today = Wednesday;  // 枚举类型变量赋值

注意点:
  • 默认值:如果不显式指定枚举值,枚举的值会从 0 开始递增。例如,Monday 默认是 0,Tuesday 是 1,依此类推,除非显式地指定其他值。
  • 类型大小:在 C 语言中,枚举类型本质上是整数类型。不同的编译器可能会为枚举选择不同的基础类型(通常是 int),因此你不能直接确定其内存占用,除非使用 sizeof 来确认。

4. 类型别名(typedef

typedef 关键字允许为已存在的类型创建别名。这对于构造清晰、易读的代码特别有用。

定义:
typedef struct Student {
    char name[50];
    int age;
    float score;
} Student;  // 创建 Student 类型别名
使用:
Student s1;  // 现在可以直接使用 Student 来定义变量
注意点:
  • typedef 并不创建新的数据类型,它只是给现有的数据类型起一个新的名字。

5. 指针和结构体的关系

结构体指针在 C 中非常常见,尤其是在涉及动态内存分配、传递大型结构体时。结构体指针可以通过 -> 操作符来访问结构体成员。

示例:
struct Student {
    char name[50];
    int age;
};

struct Student *p = malloc(sizeof(struct Student));
strcpy(p->name, "Tom");
p->age = 21;
free(p);

注意点:
  • 动态内存分配:如果使用指针,需要手动管理内存分配和释放,避免内存泄漏。
  • NULL 检查:在访问结构体指针之前,始终确保指针非 NULL。

6. 内存管理

C 语言不提供自动垃圾回收,结构体和其他数据类型需要手动管理内存。特别是使用动态分配内存时,必须确保在不再使用时释放内存:

  • 使用 malloc() 或 calloc() 分配内存。
  • 使用 free() 释放内存。
示例:
struct Student *s = malloc(sizeof(struct Student));
if (s != NULL) {
    strcpy(s->name, "John");
    s->age = 22;
    free(s);  // 释放内存
}

总结

构造数据类型是 C 语言中非常强大的功能,它允许你根据具体需求设计和使用复杂的数据结构。使用时要特别注意以下几个问题:

  • 内存对齐和填充:结构体的内存布局可能会受到对齐的影响,要注意成员的顺序和内存大小。
  • 内存管理:如果使用了动态内存分配,记得手动管理内存。
  • 指针的使用:指针在结构体和共用体中经常被使用,确保指针有效,并且注意内存的释放。

你可能感兴趣的:(linux,学习,算法)