深入理解C语言结构体和联合体

发布时间:2024年01月22日

目录

结构体(Structures)

什么是结构体?

结构体的定义与声明

结构体的访问

结构体的嵌套

联合体(Unions)

什么是联合体?

联合体的定义与声明

联合体的访问

联合体的应用

结构体与联合体的比较

1. 内存分配

2. 成员访问

3. 应用场景

4. 内存优化

结构体练习

学生信息管理:

日期管理:

联合体练习

答案

学生信息管理:

?日期管理:

变体数据类型

网络协议处理:

C语言是一门被广泛应用于系统级编程和嵌入式系统开发的高级编程语言。在C语言中,结构体(Structures)和联合体(Unions)是两种重要的数据结构,允许程序员组织和管理不同类型的数据。本文将深入浅出地介绍C语言中的结构体和联合体。

结构体(Structures)

什么是结构体?

结构体是一种用户自定义的数据类型,允许将不同类型的数据组织在一个单一的数据结构中。结构体的每个成员可以是不同的数据类型,可以包含基本数据类型,数组,甚至其他结构体。

结构体的定义与声明

在C语言中,结构体的定义和声明通常分为两个步骤。首先是定义结构体的模板,然后声明具体的结构体变量。

// 结构体定义
struct Person {
    char name[50];
    int age;
    float height;
};

// 结构体声明
struct Person person1, person2;

上面的例子中,我们定义了一个名为Person的结构体,包含了姓名、年龄和身高三个成员。然后通过声明两个Person类型的变量person1person2

结构体的访问

访问结构体的成员使用点操作符 .

// 赋值
strcpy(person1.name, "John Doe");
person1.age = 30;
person1.height = 175.5;

// 访问
printf("Name: %s\n", person1.name);
printf("Age: %d\n", person1.age);
printf("Height: %.2f\n", person1.height);

结构体的嵌套

结构体可以嵌套在其他结构体中,形成复杂的数据结构:

struct Date {
    int day;
    int month;
    int year;
};

struct Student {
    char name[50];
    struct Date dob; // 结构体嵌套
    int roll_number;
};

联合体(Unions)

什么是联合体?

联合体是一种特殊的数据类型,允许在同一内存位置存储不同的数据类型。和结构体不同的是,联合体的成员共享同一块内存。

联合体的定义与声明

// 联合体定义
union Data {
    int i;
    float f;
    char str[20];
};

// 联合体声明
union Data data1, data2;

上述代码定义了一个名为 Data 的联合体,包含了一个整数、一个浮点数和一个字符数组。然后通过声明两个 Data 类型的变量 data1data2

联合体的访问

访问联合体的成员使用点操作符 .

data1.i = 10;
printf("Integer: %d\n", data1.i);

data1.f = 3.14;
printf("Float: %.2f\n", data1.f);

strcpy(data1.str, "Hello");
printf("String: %s\n", data1.str);

联合体的一个关键特性是,它的所有成员共享同一块内存。因此,对一个成员的修改会影响其他成员。

联合体的应用

联合体常用于需要在不同数据类型之间共享同一内存位置的场景,节省内存空间。例如,一个网络协议包可能包含多个字段,但在任一时刻只有其中一个字段是有效的。

union ProtocolData {
    int packetType;
    float sensorData;
    char message[256];
};

结构体与联合体的比较

1. 内存分配

  • 结构体: 结构体的内存分配是按照成员的顺序依次分配的,每个成员都占据独立的内存空间。这意味着结构体的大小等于所有成员大小之和。
struct Person {
    char name[50];
    int age;
    float height;
};

在上述例子中,Person 结构体的大小为 50 (name) + 4 (age) + 4 (height) = 58 字节。

  • 联合体: 联合体的内存分配是所有成员共享同一块内存,它们的起始地址相同。联合体的大小等于最大成员的大小。
union Data {
    int i;
    float f;
    char str[20];
};

在上述例子中,Data 联合体的大小等于最大成员 str[20] 的大小,即 20 字节。

2. 成员访问

  • 结构体: 结构体的成员访问使用点操作符 .,每个成员都有独立的命名空间。
struct Person person1;
person1.age = 25;
  • 联合体: 联合体的成员访问也使用点操作符 .,但由于所有成员共享同一块内存,对一个成员的修改会影响其他成员。
union Data data1;
data1.i = 42;
printf("%f\n", data1.f);  // 输出的是由浮点数解释的42

3. 应用场景

  • 结构体: 适用于需要同时存储多个不同类型的数据,且这些数据有各自的意义和用途的情况。例如,表示一个人的信息。
struct Person {
    char name[50];
    int age;
    float height;
};
  • 联合体: 适用于需要在同一块内存中共享不同类型的数据,且在任一时刻只有一个成员有效的情况。例如,一个网络协议包可能包含多个字段,但在特定情况下只有一个字段有效
union ProtocolData {
    int packetType;
    float sensorData;
    char message[256];
};

4. 内存优化

  • 结构体: 由于结构体的内存是按照成员顺序分配的,相邻的成员可能存在内存对齐的空隙,造成内存浪费。

  • 联合体: 联合体的内存共享机制可能导致在不同成员切换时的数据混淆,使用联合体时需要特别小心,确保对数据的访问和修改都是合理的。

结构体练习

  1. 学生信息管理:

    定义一个结构体 Student 表示学生信息,包括学生姓名(字符串)、学号(整数)、成绩(浮点数)。

// 结构体定义
struct Student {
    char name[50];
    int studentID;
    float grade;
};

// 结构体声明
struct Student student1, student2;

???编写代码完成以下任务,

  • 输入学生信息。
  • 输出学生信息。

日期管理:

定义一个结构体 Date 表示日期,包括年(整数)、月(整数)、日(整数)。

// 结构体定义
struct Date {
    int year;
    int month;
    int day;
};

// 结构体声明
struct Date date1, date2;

编写代码完成以下任务:

  • 输入日期。
  • 输出日期

联合体练习

  1. 变体数据类型:

    定义一个联合体 Variant 表示变体数据类型,包括整数(int)、浮点数(float)和字符串(char数组)

// 联合体定义
union Variant {
    int intValue;
    float floatValue;
    char stringValue[20];
};

// 联合体声明
union Variant data1, data2;

编写代码完成以下任务:

  • 输入和输出整数、浮点数、字符串。

网络协议处理:

定义一个联合体 ProtocolData 表示网络协议数据包,包括数据类型(整数)、传感器数据(浮点数)和消息(char数组)。

// 联合体定义
union ProtocolData {
    int packetType;
    float sensorData;
    char message[256];
};

// 联合体声明
union ProtocolData packet1, packet2;

编写代码完成以下任务:

  • 输入和输出数据类型、传感器数据、消息。

答案

结构体练习

学生信息管理:

#include <stdio.h>

int main() {
    // 输入学生信息
    printf("Enter student1 details:\n");
    printf("Name: ");
    scanf("%s", student1.name);
    printf("Student ID: ");
    scanf("%d", &student1.studentID);
    printf("Grade: ");
    scanf("%f", &student1.grade);

    // 输出学生信息
    printf("\nStudent1 details:\n");
    printf("Name: %s\n", student1.name);
    printf("Student ID: %d\n", student1.studentID);
    printf("Grade: %.2f\n", student1.grade);

    return 0;
}

?日期管理:

#include <stdio.h>

int main() {
    // 输入日期
    printf("Enter date1 details:\n");
    printf("Year: ");
    scanf("%d", &date1.year);
    printf("Month: ");
    scanf("%d", &date1.month);
    printf("Day: ");
    scanf("%d", &date1.day);

    // 输出日期
    printf("\nDate1 details:\n");
    printf("Year: %d\n", date1.year);
    printf("Month: %d\n", date1.month);
    printf("Day: %d\n", date1.day);

    return 0;
}

联合体练习

变体数据类型

#include <stdio.h>

int main() {
    // 输入和输出整数
    printf("Enter an integer: ");
    scanf("%d", &data1.intValue);
    printf("Integer: %d\n", data1.intValue);

    // 输入和输出浮点数
    printf("Enter a float: ");
    scanf("%f", &data1.floatValue);
    printf("Float: %.2f\n", data1.floatValue);

    // 输入和输出字符串
    printf("Enter a string: ");
    scanf("%s", data1.stringValue);
    printf("String: %s\n", data1.stringValue);

    return 0;
}

网络协议处理:

#include <stdio.h>

int main() {
    // 输入和输出数据类型
    printf("Enter packetType: ");
    scanf("%d", &packet1.packetType);
    printf("Packet Type: %d\n", packet1.packetType);

    // 输入和输出传感器数据
    printf("Enter sensorData: ");
    scanf("%f", &packet1.sensorData);
    printf("Sensor Data: %.2f\n", packet1.sensorData);

    // 输入和输出消息
    printf("Enter message: ");
    scanf("%s", packet1.message);
    printf("Message: %s\n", packet1.message);

    return 0;
}

文章来源:https://blog.csdn.net/weixin_40345245/article/details/135676939
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。