首页...结构体与共用体的基础与应用
C语言程序设计第八章 结构体与共用体/第一节

结构体与共用体的基础与应用

2026-03-24

第八章 结构体与共用体

第一节 结构体与共用体的基础

概述

本节内容主要围绕C语言中的结构体(struct)和共用体(union)展开。结构体和共用体是C语言中非常重要的复合数据类型,它们能够将多个不同类型的数据组合成一个整体,极大地增强了程序的数据组织能力和表达能力。通过本节的学习,考生将掌握结构体与共用体的定义、声明、访问以及应用,理解它们的内存布局和区别,能够灵活运用结构体和共用体解决实际编程问题。

学习目标

  • 理解结构体和共用体的基本概念及定义方式
  • 掌握结构体与共用体的内存分配原理
  • 熟悉结构体与共用体的声明、初始化和访问方法
  • 掌握结构体数组、指针及嵌套结构体的使用
  • 理解共用体的特殊存储方式及适用场景
  • 通过实例掌握结构体与共用体的综合应用

核心概念

结构体(struct)

结构体是一种用户自定义的数据类型,它可以将不同类型的变量组合在一起,形成一个整体。结构体中的每个变量称为“成员”或“域”,这些成员可以是不同的数据类型。

结构体的定义形式为:

struct 结构体名 {
    数据类型 成员名1;
    数据类型 成员名2;
    ...
};

结构体变量可以用“.”访问成员,也可以通过指针用“->”访问。

共用体(union)

共用体也是一种用户自定义的数据类型,它与结构体类似,但所有成员共用同一块内存空间。共用体的大小等于最大成员的大小,任何时候只能存储一个成员的值。

共用体的定义形式和结构体类似:

union 共用体名 {
    数据类型 成员名1;
    数据类型 成员名2;
    ...
};

成员访问

  • 对结构体变量,使用.操作符访问成员。
  • 对结构体指针,使用->操作符访问成员。

内存布局

  • 结构体:每个成员占用独立内存,整体大小是所有成员大小之和(考虑对齐)。
  • 共用体:所有成员共享同一内存块,整体大小等于最大成员大小。

原理分析

结构体的内存分配原理

结构体的内存是按照成员声明顺序依次分配的,但为了提高访问效率,编译器通常会进行内存对齐,即成员地址按一定规则对齐到特定边界(如4字节对齐)。这可能导致结构体内部产生填充字节。

例如:

struct Example {
    char a;      // 1字节
    int b;       // 4字节
};

内存布局可能是:

  • a占1字节
  • 3字节填充
  • b占4字节
    总大小为8字节。

共用体的内存分配原理

共用体所有成员共享同一块内存,大小为最大成员所占空间。
例如:

union Example {
    int a;    // 4字节
    float b;  // 4字节
    char c;   // 1字节
};

共用体大小是4字节,所有成员共用这4字节空间。

结构体与共用体的区别

特性 结构体 共用体
内存分配 每个成员独立分配内存 所有成员共用同一内存空间
大小 成员大小之和(含填充) 最大成员大小
同时存储多个成员 可以 不可以
用途 组织多种数据 节省内存,表示同一数据的不同解释

详细内容

1. 结构体的定义与声明

结构体的定义包括结构体类型的声明和结构体变量的声明。结构体可以单独定义,也可以在定义时同时声明变量。

struct Person {
    char name[20];
    int age;
    float height;
};

struct Person p1; // 声明结构体变量p1

也可以通过typedef定义结构体别名,简化变量声明:

typedef struct {
    char name[20];
    int age;
} Person;

Person p2; // 使用别名声明变量

2. 结构体成员访问

访问结构体成员主要用.->操作符。示例如下:

p1.age = 25;
printf("Name: %s, Age: %d", p1.name, p1.age);

当使用结构体指针时:

struct Person *ptr = &p1;
ptr->age = 30;

3. 结构体的初始化

结构体变量可以在声明时初始化,也可以逐个赋值。

struct Point {
    int x;
    int y;
};

struct Point pt1 = {10, 20};

4. 结构体数组

结构体数组是结构体类型的数组,用来存储多个结构体变量。

struct Student {
    char name[20];
    int score;
};

struct Student students[3] = { {"Alice", 90}, {"Bob", 85}, {"Cathy", 88} };

访问数组元素成员:

printf("%s's score: %d", students[1].name, students[1].score);

5. 结构体指针

结构体指针指向结构体变量的地址,便于传递和操作大型结构体。

struct Student *p = &students[0];
printf("%s", p->name);

6. 嵌套结构体

结构体成员也可以是结构体类型,实现复杂数据结构。

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

struct Person {
    char name[20];
    struct Date birthday;
};

访问嵌套成员:

p1.birthday.year = 2000;

7. 共用体的定义与特点

共用体定义与结构体类似,但所有成员共用内存。

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

union Data data;
data.i = 10;

注意,共用体在不同成员赋值时会覆盖之前的内容。

8. 共用体的实际用途

共用体常用于节省内存,或实现不同数据类型的“视图”,例如:

  • 解析网络数据包
  • 存储不同类型的消息
  • 实现多态结构

实例分析

实例一:学生信息管理结构体

背景:需要存储学生的姓名、年龄和成绩信息。

#include <stdio.h>

struct Student {
    char name[20];
    int age;
    float score;
};

int main() {
    struct Student s1 = {"张三", 20, 88.5};
    printf("Name: %s, Age: %d, Score: %.2f\n", s1.name, s1.age, s1.score);
    return 0;
}

分析:定义结构体Student,声明变量s1并初始化。通过.访问成员打印学生信息。

结论:结构体便于组织相关数据,易于管理。


实例二:共用体实现多类型数据存储

背景:一个变量可以存储整数、浮点数或字符串。

#include <stdio.h>
#include <string.h>

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

int main() {
    union Data data;
    data.i = 100;
    printf("data.i = %d\n", data.i);

    data.f = 98.6;
    printf("data.f = %.2f\n", data.f);

    strcpy(data.str, "Hello");
    printf("data.str = %s\n", data.str);

    return 0;
}

分析:由于共用体共享内存,赋值后前面数据被覆盖。

结论:共用体适合存储多种类型但同一时刻只需一种数据的场景。


实例三:嵌套结构体表示日期和时间

背景:需要存储事件的日期和时间。

#include <stdio.h>

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

struct Time {
    int hour;
    int minute;
    int second;
};

struct Event {
    char name[30];
    struct Date date;
    struct Time time;
};

int main() {
    struct Event e = {"会议", {2024, 6, 15}, {14, 30, 0}};
    printf("Event: %s\nDate: %d-%d-%d\nTime: %d:%d:%d\n",
            e.name, e.date.year, e.date.month, e.date.day, e.time.hour, e.time.minute, e.time.second);
    return 0;
}

分析:通过嵌套结构体,清晰表达复杂数据。

结论:嵌套结构体增强数据的层次性和可读性。


常见误区

  1. 误区:结构体成员的顺序不影响内存大小

    • 正确做法:成员顺序影响内存对齐和填充,合理排序可节省空间。
  2. 误区:共用体可以同时存储多个成员的值

    • 正确做法:共用体同一时刻只存储一个成员,赋值会覆盖之前数据。
  3. 误区:结构体变量初始化时可以省略成员

    • 正确做法:初始化应按声明顺序完整赋值,缺省成员值不确定。
  4. 误区:结构体指针访问成员用.而非->

    • 正确做法:结构体指针访问成员必须用->操作符。
  5. 误区:共用体和结构体的声明及变量定义混淆

    • 正确做法:结构体和共用体的定义需区分类型声明和变量声明,避免语法错误。

应用场景

  • 数据封装:将相关数据组合成结构体,便于管理和传递,如学生信息、坐标点等。
  • 节省内存:共用体在嵌入式系统中用来节省内存资源,尤其存储多种状态或数据时。
  • 协议解析:网络协议数据包中不同字段解释为不同类型,使用共用体方便解析。
  • 多态实现:通过共用体配合标志变量,实现类似多态的功能。
  • 复杂数据结构:嵌套结构体构建树、链表、图等复杂结构。

知识拓展

  • 结构体对齐与填充:深入了解编译器如何进行内存对齐,利用#pragma pack调整结构体大小。
  • 位域结构体:结构体成员可以定义为位域,控制占用位数,节省空间。
  • 联合体与枚举结合:通过枚举标志联合体当前存储的有效成员,实现安全访问。
  • 结构体函数指针:结构体成员可以包含函数指针,实现面向对象编程思想。
  • 动态结构体:结合指针和动态内存分配,灵活管理结构体数组和链表。

总结回顾

本节系统介绍了C语言中结构体和共用体的基础知识及应用。结构体作为一种组合多种数据类型的复合类型,是组织复杂数据的有力工具;共用体通过共享内存实现多种数据类型共存但互斥存储,适合节约内存和多类型数据解释。掌握结构体和共用体的定义、声明、访问、初始化及内存原理,是深入理解C语言数据结构的基础。通过实例演练,理解结构体数组、指针、嵌套结构体和共用体的实际应用,避免常见误区,能够有效提高编程能力和代码质量。希望考生能结合实际编程多加练习,牢固掌握本节内容,为计算机等级考试二级C语言程序设计打下坚实基础。


重点知识点

1

结构体的定义与声明方法

2

结构体成员访问与初始化方式

3

结构体的内存分配和内存对齐原理

4

共用体的定义及其内存共享机制

5

结构体与共用体的区别和适用场景

6

结构体数组和结构体指针的使用

7

嵌套结构体的概念及应用

8

共用体的典型应用及注意事项

9

结构体和共用体的常见误区与纠正

10

结构体与共用体在实际项目中的应用场景