首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >C 语言 | 结构体详解:自定义数据类型的艺术

C 语言 | 结构体详解:自定义数据类型的艺术

作者头像
钮祜禄.爱因斯晨
发布2025-08-12 08:23:53
发布2025-08-12 08:23:53
31000
代码可运行
举报
运行总次数:0
代码可运行

个人主页-爱因斯晨

文章专栏-C语言

最近发现一个巨牛的人工智能的学习网站,给大家分享一下~可点击下方链接查看!

人工智能学习网站

加速更新中!!

结构体是 C 语言中一种强大的自定义数据类型,它允许我们将不同类型的数据组合在一起,形成一个有机的整体。掌握结构体是编写复杂 C 程序的基础,也是理解面向对象编程思想的前奏。本文将系统解析结构体的方方面面,助你灵活运用这一重要特性。

一、结构体的基本概念

定义:结构体(struct)是由一系列具有相同或不同数据类型的数据构成的数据集合

核心价值

  • 将相关数据封装在一起,提高代码的可读性和维护性
  • 模拟现实世界中的实体,如学生、书籍、坐标等
  • 为复杂数据结构(如链表、树)提供基础
  • 便于组织和处理大量相关数据

声明格式

代码语言:javascript
代码运行次数:0
运行
复制
struct 结构体名 {
    数据类型 成员名1;
    数据类型 成员名2;
    // ...更多成员
};

二、结构体的定义与使用

基本定义与初始化

代码语言:javascript
代码运行次数:0
运行
复制
// 定义结构体类型
struct Student {
    char name[20];  // 姓名
    int age;        // 年龄
    float score;    // 成绩
};

// 声明结构体变量并初始化
struct Student stu1 = {"张三", 18, 95.5f};

访问结构体成员:使用点运算符(.)

代码语言:javascript
代码运行次数:0
运行
复制
// 访问成员
printf("姓名: %s\n", stu1.name);
printf("年龄: %d\n", stu1.age);

// 修改成员值
stu1.age = 19;
stu1.score = 97.0f;

结构体变量的赋值

代码语言:javascript
代码运行次数:0
运行
复制
struct Student stu2;
stu2 = stu1;  // 整体赋值,将stu1的所有成员复制到stu2

三、结构体与指针

结构体指针的定义与使用

代码语言:javascript
代码运行次数:0
运行
复制
struct Student *pStu;  // 声明结构体指针
pStu = &stu1;          // 指向结构体变量

// 通过指针访问成员:使用箭头运算符(->)
printf("姓名: %s\n", pStu->name);
printf("年龄: %d\n", pStu->age);

// 也可以使用解引用方式
printf("成绩: %.1f\n", (*pStu).score);

动态分配结构体内存

代码语言:javascript
代码运行次数:0
运行
复制
// 动态创建结构体变量
struct Student *p = (struct Student*)malloc(sizeof(struct Student));
if (p != NULL) {
    strcpy(p->name, "李四");
    p->age = 20;
    p->score = 92.5f;
    
    // 使用完毕释放内存
    free(p);
    p = NULL;
}

四、结构体数组

定义与初始化

代码语言:javascript
代码运行次数:0
运行
复制
// 定义结构体数组
struct Student class[3] = {
    {"张三", 18, 95.5f},
    {"李四", 19, 92.0f},
    {"王五", 18, 88.5f}
};

访问数组元素

代码语言:javascript
代码运行次数:0
运行
复制
// 访问第二个学生的信息
printf("第二个学生: %s, %d岁, 成绩: %.1f\n", 
       class[1].name, 
       class[1].age, 
       class[1].score);

// 使用指针遍历数组
struct Student *p;
for (p = class; p < class + 3; p++) {
    printf("%s ", p->name);
}

五、结构体嵌套

结构体内部包含其他结构体

代码语言:javascript
代码运行次数:0
运行
复制
// 定义日期结构体
struct Date {
    int year;
    int month;
    int day;
};

// 定义包含日期的结构体
struct Book {
    char title[50];
    char author[30];
    struct Date publishDate;  // 嵌套结构体
    float price;
};

嵌套结构体的使用

代码语言:javascript
代码运行次数:0
运行
复制
struct Book book1 = {
    "C语言编程",
    "张明",
    {2020, 5, 18},  // 初始化嵌套的日期结构体
    59.9f
};

// 访问嵌套结构体的成员
printf("出版日期: %d年%d月%d日\n",
       book1.publishDate.year,
       book1.publishDate.month,
       book1.publishDate.day);

六、结构体与函数

结构体作为函数参数

代码语言:javascript
代码运行次数:0
运行
复制
// 结构体传值
void printStudent(struct Student s) {
    printf("姓名: %s, 年龄: %d, 成绩: %.1f\n",
           s.name, s.age, s.score);
}

// 调用函数
printStudent(stu1);

结构体指针作为函数参数(更高效)

代码语言:javascript
代码运行次数:0
运行
复制
// 结构体指针传参
void updateScore(struct Student *s, float newScore) {
    s->score = newScore;
}

// 调用函数
updateScore(&stu1, 98.0f);

函数返回结构体

代码语言:javascript
代码运行次数:0
运行
复制
struct Student createStudent(char *name, int age, float score) {
    struct Student s;
    strcpy(s.name, name);
    s.age = age;
    s.score = score;
    return s;
}

// 使用
struct Student stu3 = createStudent("赵六", 19, 94.5f);

七、结构体的内存对齐

内存对齐的概念:结构体成员在内存中的存放地址需要满足一定的对齐要求,并非简单连续排列

对齐规则

  • 每个成员的起始地址是该成员类型大小的整数倍
  • 结构体总大小是其最大成员类型大小的整数倍
  • 嵌套结构体的对齐以其最大成员类型大小为基准

示例分析

代码语言:javascript
代码运行次数:0
运行
复制
struct Example {
    char a;    // 1字节
    int b;     // 4字节
    char c;    // 1字节
};
// 该结构体大小为12字节,而非6字节
// 内存布局:a(1) + 填充(3) + b(4) + c(1) + 填充(3)

修改对齐方式(编译器特定):

代码语言:javascript
代码运行次数:0
运行
复制
// GCC编译器:设置1字节对齐
#pragma pack(1)
struct Example {
    char a;
    int b;
    char c;
};
#pragma pack()  // 恢复默认对齐
// 此时结构体大小为6字节

八、typedef 与结构体

使用 typedef 简化结构体声明

代码语言:javascript
代码运行次数:0
运行
复制
// 方式1
typedef struct Student {
    char name[20];
    int age;
    float score;
} Student;  // 别名

// 方式2
struct _Teacher {
    char name[20];
    int id;
};
typedef struct _Teacher Teacher;

使用别名声明变量

代码语言:javascript
代码运行次数:0
运行
复制
Student stu4;  // 无需再写struct关键字
Teacher t1;

九、结构体的实际应用场景

表示复杂实体:如学生、员工、商品等包含多个属性的实体

数据集合管理:将相关数据组织在一起,方便批量处理

文件操作:读写二进制文件时,结构体可直接映射文件记录

实现数据结构:链表节点、树节点等都以结构体为基础

代码语言:javascript
代码运行次数:0
运行
复制
// 链表节点结构体
struct Node {
    int data;           // 数据域
    struct Node *next;  // 指针域,指向下一个节点
};

硬件编程:映射硬件寄存器,方便操作硬件设备

十、结构体使用注意事项

避免结构体过大:过大的结构体传值会影响性能,建议使用指针传递

注意内存对齐:了解内存对齐规则,避免内存空间浪费

初始化所有成员:结构体变量声明后应初始化所有成员,避免使用未初始化的值

字符串处理:结构体中的字符串成员需要注意缓冲区溢出问题

动态内存管理:包含指针成员的结构体需要特别注意深拷贝和内存释放

代码语言:javascript
代码运行次数:0
运行
复制
// 包含指针成员的结构体
struct Data {
    int *numbers;
    int count;
};

// 深拷贝示例
void copyData(struct Data *dest, struct Data *src) {
    dest->count = src->count;
    dest->numbers = (int*)malloc(src->count * sizeof(int));
    memcpy(dest->numbers, src->numbers, src->count * sizeof(int));
}

结构体是 C 语言中实现数据封装的重要手段,它让我们能够以更接近现实世界的方式来组织和处理数据。掌握结构体不仅能提高代码的结构化程度,也能为学习更高级的数据结构和编程语言打下坚实基础。在实际编程中,合理设计结构体可以使代码更加清晰、高效和易于维护。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-07-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 个人主页-爱因斯晨
  • 文章专栏-C语言
  • 人工智能学习网站
  • 一、结构体的基本概念
  • 二、结构体的定义与使用
  • 三、结构体与指针
  • 四、结构体数组
  • 五、结构体嵌套
  • 六、结构体与函数
  • 七、结构体的内存对齐
  • 八、typedef 与结构体
  • 九、结构体的实际应用场景
  • 十、结构体使用注意事项
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档