【重新认识C语言----结构体篇】

news/2025/2/9 3:37:25 标签: c语言

目录

-----------------------------------------begin-------------------------------------

引言

1. 结构体的基本概念

1.1 为什么需要结构体?

1.2 结构体的定义

2. 结构体变量的声明与初始化

2.1 声明结构体变量

2.2 初始化结构体变量

3. 结构体成员的访问

3.1 使用点运算符(.)

3.2 结构体指针与箭头运算符(->)

4. 结构体的内存布局

4.1 内存对齐规则

4.2 手动控制内存对齐

5. 结构体的高级用法

5.1 结构体数组

5.2 嵌套结构体

5.3 结构体与函数

5.4 使用typedef简化结构体类型名

6. 结构体与联合体(Union)的区别

7. 综合示例:学生管理系统

8. 常见问题与注意事项

结语

路过的佬们点点关注哦~

你们的鼓励是我前进的动力~

-------------------------------------------end-------------------------------------


-----------------------------------------begin-------------------------------------

引言

在C语言编程中,结构体(Structure) 是一种非常重要的复合数据类型。它允许开发者将多个不同类型的变量组合成一个逻辑单元,从而更高效地管理复杂数据。无论是实现链表、树等数据结构,还是描述现实世界中的实体(如学生、商品等),结构体都扮演着核心角色。本文将详细讲解结构体的定义、使用及高级特性,帮助读者彻底掌握这一关键概念。


1. 结构体的基本概念

1.1 为什么需要结构体?

假设我们需要描述一个学生的信息,包括姓名(字符串)、学号(整数)、年龄(整数)和成绩(浮点数)。如果单独使用多个变量来存储这些信息,代码会变得冗长且难以维护。例如:

char name[20];
int id;
int age;
float score;

结构体可以将这些变量封装为一个整体,使数据管理更加清晰。

1.2 结构体的定义

结构体通过 struct 关键字定义,语法如下:

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

示例:定义一个学生结构体

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

2. 结构体变量的声明与初始化

2.1 声明结构体变量

结构体定义后,可以通过两种方式声明变量:

  1. 在定义结构体时直接声明变量

    struct Student {
        // 成员定义
    } stu1, stu2;  // 直接声明变量stu1和stu2

  2. 通过结构体类型名声明变量

    struct Student stu3;  // 声明一个Student类型的变量stu3

    2.2 初始化结构体变量

    结构体变量可以在声明时初始化,或通过赋值操作初始化。
    示例:

// 声明时初始化
struct Student stu1 = {"Alice", 1001, 18, 90.5};

// 单独赋值初始化
struct Student stu2;
strcpy(stu2.name, "Bob");
stu2.id = 1002;
stu2.age = 19;
stu2.score = 85.0;

3. 结构体成员的访问

3.1 使用点运算符(.

通过 . 运算符可以直接访问结构体变量的成员:

printf("学生姓名:%s\n", stu1.name);
printf("学号:%d\n", stu1.id);

3.2 结构体指针与箭头运算符(->

如果通过指针访问结构体成员,需使用 -> 运算符:

struct Student *pStu = &stu1;
printf("年龄:%d\n", pStu->age);  // 等价于 (*pStu).age

4. 结构体的内存布局

4.1 内存对齐规则

为了提高内存访问效率,结构体的成员在内存中遵循对齐规则:

  • 对齐数(Alignment):成员的大小与编译器默认对齐数中的较小值。

  • 起始地址:每个成员的起始地址必须是对齐数的整数倍。

  • 总大小:结构体的总大小是对齐数最大值的整数倍。

示例:

struct Example {
    char c;     // 1字节,对齐数为1
    int i;      // 4字节,对齐数为4
    double d;   // 8字节,对齐数为8
};

内存布局分析:

  • char c 占1字节,起始地址0。

  • int i 对齐数为4,起始地址需是4的倍数,因此填充3字节(地址1~3),起始地址4。

  • double d 对齐数为8,起始地址8。
    总大小 = 1 + 3(填充) + 4 + 8 = 16字节。

4.2 手动控制内存对齐

通过 #pragma pack(n) 可以修改默认对齐数(n为1、2、4、8等):

#pragma pack(1)  // 设置为1字节对齐
struct PackedExample {
    char c;
    int i;
    double d;
};
#pragma pack()   // 恢复默认对齐

此时结构体总大小为 1 + 4 + 8 = 13字节。

5. 结构体的高级用法

5.1 结构体数组

结构体数组用于存储多个相同类型的结构体变量。
示例:

struct Student students[3] = {
    {"Alice", 1001, 18, 90.5},
    {"Bob", 1002, 19, 85.0},
    {"Charlie", 1003, 20, 92.0}
};

5.2 嵌套结构体

结构体可以嵌套其他结构体作为成员。
示例:

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

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

5.3 结构体与函数

结构体可以作为函数参数或返回值传递。
示例:

// 函数参数:按值传递
void printStudent(struct Student stu) {
    printf("姓名:%s\n", stu.name);
}

// 函数参数:按指针传递(推荐,避免内存拷贝)
void updateScore(struct Student *pStu, float newScore) {
    pStu->score = newScore;
}

// 函数返回结构体
struct Student createStudent() {
    struct Student stu = {"David", 1004, 21, 88.5};
    return stu;
}

5.4 使用typedef简化结构体类型名

通过 typedef 可以为结构体定义别名,简化代码:

typedef struct Student {
    // 成员定义
} Student;  // 别名

// 声明变量
Student stu4;

6. 结构体与联合体(Union)的区别

结构体与联合体(union)的区别在于内存分配方式:

  • 结构体:每个成员拥有独立的内存空间,总大小为所有成员大小之和(考虑对齐)。

  • 联合体:所有成员共享同一块内存空间,总大小等于最大成员的大小。

7. 综合示例:学生管理系统

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

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

void printStudent(const Student *stu) {
    printf("姓名:%s\t学号:%d\t成绩:%.1f\n", stu->name, stu->id, stu->score);
}

int main() {
    Student students[3];
    
    // 输入学生信息
    for (int i = 0; i < 3; i++) {
        printf("输入第%d个学生的姓名、学号和成绩:", i+1);
        scanf("%s %d %f", students[i].name, &students[i].id, &students[i].score);
    }

    // 输出学生信息
    printf("\n学生列表:\n");
    for (int i = 0; i < 3; i++) {
        printStudent(&students[i]);
    }

    return 0;
}

8. 常见问题与注意事项

  • 结构体赋值

    结构体变量可以直接赋值给同类型的变量(按值拷贝):

Student stu1 = {"Alice", 1001, 90.5};
Student stu2 = stu1;  // 合法,内存拷贝
  • 结构体大小计算

    使用 sizeof 运算符获取结构体大小,但需注意内存对齐的影响。

  • 结构体与动态内存分配

    结构体指针可以结合 malloc 实现动态内存分配:

Student *pStu = (Student*)malloc(sizeof(Student));
free(pStu);

结语

结构体是C语言中组织复杂数据的核心工具,其灵活性和高效性使其在系统编程、嵌入式开发等领域广泛应用。通过本文的学习,读者应能够熟练定义、操作结构体,并理解其底层内存布局。建议结合实际项目练习,进一步巩固这一重要概念。

路过的佬们点点关注哦~
你们的鼓励是我前进的动力~

-------------------------------------------end-------------------------------------


http://www.niftyadmin.cn/n/5845494.html

相关文章

神经网络常见激活函数 4-LeakyReLU函数

LeakyReLU LeakyReLU&#xff1a; Leaky Rectified Linear Unit 函数导函数 LeakyReLU函数 L e a k y R e L U { x x > 0 p x x < 0 p ∈ ( 0 , 1 ) \rm Leaky{ReLU} \left\{ \begin{array}{} x \quad x>0 \\ px \quad x<0 \end{array} \right. \quad p \in …

LeetCode 每日一题 2025/1/27-2025/2/2

记录了初步解题思路 以及本地实现代码&#xff1b;并不一定为最优 也希望大家能一起探讨 一起进步 目录 1/27 45. 跳跃游戏 II1/28 119. 杨辉三角 II1/29 219. 存在重复元素 II1/30 350. 两个数组的交集 II1/31 541. 反转字符串 II2/1 81. 搜索旋转排序数组 II2/2 598. 区间加法…

Kotlin协程详解——协程取消与超时

目录 一、协程取消 1.取消协程的执行 2.使计算代码可取消 3.在finally中释放资源 4.运行不能取消的代码块 二、协程超时 异步超时与资源管理 一、协程取消 1.取消协程的执行 在一个长时间运行的应用程序中&#xff0c;你也许需要对你的后台协程进行细粒度的控制。 比如…

LeetCode 72.编辑距离

要解决LeetCode 72题“编辑距离”问题&#xff0c;我们可以使用动态规划的方法。以下是详细的C解题思路和实现过程&#xff1a; 解题思路 问题分析 编辑距离问题要求将字符串 word1 转换为 word2 所需的最少操作次数&#xff0c;允许的操作包括插入、删除和替换字符。动态规划…

零基础学习书生.浦语大模型--基础岛

第二关:玩转书生[多模态对话]和[AI搜索]产品 任务一&#xff1a;使用MindSearch 任务二&#xff1a;尝试使用书生.浦语 尝试让其写一段Self-Attention网络模块代码 import torch import torch.nn as nn import torch.nn.functional as Fclass SelfAttention(nn.Module):def _…

Explain 是 SQL 查询优化中非常重要的工具,它用于分析 SQL 查询的执行计划

Explain 是 SQL 查询优化中非常重要的工具&#xff0c;它用于分析 SQL 查询的执行计划https://mp.weixin.qq.com/s/QKra-Sp5JoaEPSCqfffOtA

Spring Cloud 01 - 微服务概述

微服务概述 文章目录 微服务概述一&#xff1a;分布式和微服务1、什么是微服务&#xff1f;2&#xff1a;什么是分布式3、联系与区别是什么&#xff1f; 2&#xff1a;最终技术搭配方案 一&#xff1a;分布式和微服务 1、什么是微服务&#xff1f; 微服务架构是团队面对互联网…

centos虚拟机迁移没有ip的问题

故事背景&#xff0c;我们的centos虚拟机本来是好好的&#xff0c;但是拷贝到其他电脑上就不能分配ip&#xff0c;我个人觉得这个vmware他们软件应该搞定这个啊&#xff0c;因为这个问题是每次都会出现的。 网络选桥接 网络启动失败 service network restart Restarting netw…