当前位置: 首页 > ds >正文

c语言初阶 结构体

结构体

  • C语言结构体详解
    • 1. 结构体的声明
    • 2. 结构体的定义
      • (1)结构体定义与变量的区别
      • (2)结构体嵌套​
    • 3. 结构体的初始化​
    • 4. 结构体成员的访问​
      • (1)通过结构体变量访问(.操作符)​
      • (2)通过结构体指针访问(->操作符)​
      • (3)两种访问方式的使用场景​
    • 5. 结构体传参​
      • (1)传值调用​
      • (2)传地址调用​
      • (3)两种传参方式的对比​
    • 6. 一句话总结​

C语言结构体详解

1. 结构体的声明

结构体是一些值的集合,这些值称为成员变量,每个成员可以是不同类型的变量。

声明格式

struct 结构体名 {成员变量类型 成员变量名;// 更多成员变量...
};

示例:声明一个学生结构体

// 声明学生结构体
struct Student {char name[20];  // 姓名int age;        // 年龄float score;    // 成绩
};

用结构体实例化的两种情况:​

  1. 声明结构体后实例化
struct Student {char name[20];int age;float score;
};// 实例化结构体变量
struct Student stu1;
struct Student stu2;
  1. 声明结构体的同时实例化
struct Student {char name[20];int age;float score;} stu1, stu2;  // 声明时直接实例化变量

2. 结构体的定义

(1)结构体定义与变量的区别

  • 结构体定义:描述结构体的组成,不分配内存空间
  • 结构体变量:根据结构体定义创建的具体实例,会分配内存空间

示例

// 结构体定义(不占空间)
struct Book {char title[50];float price;int page;
};// 结构体变量(占空间)
struct Book b1;  // 分配内存,大小为50 + 4 + 4 = 58字节(不考虑内存对齐)

(2)结构体嵌套​

结构体的成员可以是另一个结构体。​

示例:​

// 声明日期结构体​
struct Date {int year;int month;int day;};​
​
// 声明图书结构体,嵌套日期结构体​
struct Book {char title[50];float price;struct Date publish_date;  // 嵌套结构体作为成员​
};​
​
// 实例化嵌套结构体变量​
struct Book b1;

3. 结构体的初始化​

使用{}对结构体变量进行初始化,顺序与结构体成员声明顺序一致。​

示例1:基本初始化

struct Student {char name[20];int age;float score;};​\\完全初始化​
struct Student stu1 = {"张三", 18, 90.5f};​
​\\不完全初始化(未初始化的成员自动为0或空)​struct Student stu2 = {"李四", 19};  // score默认为0.0f

示例 2:嵌套结构体初始化

struct Date {int year;int month;int day;
};struct Book {char title[50];float price;struct Date publish_date;
};// 嵌套初始化,内部结构体用{}包裹
struct Book b1 = {"C语言教程", 39.9f, {2023, 10, 15}};

示例 3:指定成员初始化(C99 支持)

struct Student stu = {.age = 20,.name = "王五",  // 可以不按声明顺序.score = 88.0f
};

4. 结构体成员的访问​

(1)通过结构体变量访问(.操作符)​

当直接使用结构体变量时,用.操作符访问成员。​

格式结构体变量名.成员名

示例:​

struct Student {char name[20];int age;float score;};​
​
int main() {struct Student stu = {"张三", 18, 90.5f};​​// 使用.操作符访问成员​printf("姓名:%s\n", stu.name);printf("年龄:%d\n", stu.age);​​// 修改成员值​stu.age = 19;​stu.score = 92.0f;printf("修改后年龄:%d\n", stu.age);return 0;}

(2)通过结构体指针访问(->操作符)​

当使用结构体指针时,用->操作符访问成员。​

格式结构体指针->成员名

示例:​

struct Student {char name[20];int age;float score;};​
​
int main() {struct Student stu = {"张三", 18, 90.5f};struct Student *p = &stu;  // 定义结构体指针,指向stu​// 使用->操作符访问成员​printf("姓名:%s\n", p->name);printf("年龄:%d\n", p->age);​​// 修改成员值​p->age = 19;​p->score = 92.0f;printf("修改后年龄:%d\n", p->age);return 0;}

等价写法:(*指针变量).成员名

printf("姓名:%s\n", (*p).name);  // 与p->name等价

(3)两种访问方式的使用场景​

  • .操作符:适用于直接操作结构体变量的场景,代码更简洁直观​
  • ->操作符:适用于通过指针操作结构体的场景,尤其在函数传参为结构体指针时使用​

    示例:函数中访问结构体成员
// 使用.操作符(需要结构体变量)​
void print_stu(struct Student s) {printf("姓名:%s,年龄:%d\n", s.name, s.age);}​
​
// 使用->操作符(需要结构体指针)​
void print_stu_ptr(struct Student *p) {printf("姓名:%s,年龄:%d\n", p->name, p->age);}

5. 结构体传参​

结构体传参分为传值和传地址两种方式。​

(1)传值调用​

将结构体变量作为参数传递,函数内部会创建一个结构体副本。​

示例:​

struct Student {char name[20];int age;float score;};​
​
// 传值调用,接收结构体变量​
void modify_stu(struct Student s) {​s.age = 20;  // 仅修改副本,不影响原变量​s.score = 95.0f;}​
​
int main() {struct Student stu = {"张三", 18, 90.5f};modify_stu(stu);  // 传结构体变量​printf("年龄:%d\n", stu.age);  // 输出18,原变量未被修改​return 0;}

特点:​

  • 函数内部修改不会影响原结构体变量​
  • 传递大结构体时,会占用较多内存和时间(拷贝整个结构体)

(2)传地址调用​

将结构体指针作为参数传递,函数内部通过指针访问原结构体。​

示例:​

struct Student {char name[20];int age;float score;};​
​
// 传地址调用,接收结构体指针​
void modify_stu_ptr(struct Student *s) {​s->age = 20;  // 通过指针修改原变量​s->score = 95.0f;}​
​
int main() {struct Student stu = {"张三", 18, 90.5f};modify_stu_ptr(&stu);  // 传结构体地址​printf("年龄:%d\n", stu.age);  // 输出20,原变量被修改​return 0;}

特点:​

  • 函数内部修改会影响原结构体变量​
  • 仅传递 4 字节(32 位系统)的指针,节省内存和时间​
  • 更推荐使用的传参方式,尤其对于大型结构体

(3)两种传参方式的对比​

传参方式实现方式内存占用能否修改原结构体适用场景
传值调用传递结构体变量整个结构体大小不能小型结构体,无需修改原结构体
传址调用传递结构体指针4字节(32位所有场景,尤其大型结构体

推荐做法:优先使用传地址调用,既节省资源,又能灵活控制是否修改原结构体(如需保护原结构体,可在函数参数前加const)。​

示例:保护原结构体的传址调用

// 加const修饰,防止修改原结构体​
void print_stu(const struct Student *s) {printf("姓名:%s,年龄:%d\n", s->name, s->age);// s->age = 20;  // 错误,不能修改const结构体​
}

6. 一句话总结​

内容关键点
结构体声明描述结构体组成,用struct 结构体名 {成员列表};格式
结构体定义与变量定义不占空间,变量占空间,变量是结构体的具体实例
结构体初始化{}初始化,嵌套结构体需嵌套{},可不完全初始化
成员访问变量用.操作符,指针用->操作符p->member等价于(*p).member
结构体传参传值调用不修改原变量,传址调用效率高且可修改原变量,推荐传址调用
http://www.xdnf.cn/news/15467.html

相关文章:

  • 基于Flink的实时开发平台-Dinky
  • v-show和v-if的区别
  • 【C++】auto关键字 C++入门(5)
  • 数据结构(8)——二叉树(2)
  • HarmonyOS 获取设备位置信息开发指导
  • 每天一个前端小知识 Day 30 - 前端文件处理与浏览器存储机制实践
  • Rust 模块系统:控制作用域与私有性
  • 《[系统底层攻坚] 张冬〈大话存储终极版〉精读计划启动——存储架构原理深度拆解之旅》-系统性学习笔记(适合小白与IT工作人员)
  • 从零开始跑通3DGS教程:(五)3DGS训练
  • React强大且灵活hooks库——ahooks入门实践之常用场景hook
  • 实现“micro 关键字搜索全覆盖商品”并通过 API 接口提供实时数据(一个方法)
  • 【LeetCode数据结构】单链表的应用——反转链表问题、链表的中间节点问题详解
  • DVWA靶场通关笔记-XSS DOM(High级别)
  • Dubbo跨越分布式事务的最终一致性陷阱
  • 一文讲懂填充与步幅
  • AI进化论12:大语言模型的爆发——GPT系列“出圈”,AI飞入寻常百姓家
  • jenkins使用Jenkinsfile部署springboot+docker项目
  • 黑马点评系列问题之p63unlock.lua不知道怎么整
  • 线性代数学习笔记
  • Origin自带的悬浮尺子,Screen Ruler的最佳平替
  • 012_PDF处理与文档分析
  • 【unitrix】 5.0 第二套类型级二进制数基本结构体(types2.rs)
  • sqli-labs靶场通关笔记:第9关 时间盲注
  • NO.5数据结构串和KMP算法|字符串匹配|主串与模式串|KMP|失配分析|next表
  • 前端构建工具 Webpack 5 的优化策略与高级配置
  • 代码随想录算法训练营第十八天
  • Appium源码深度解析:从驱动到架构
  • nginx安装
  • [Subtitle Edit] 语言文件管理.xml | 测试框架(VSTest) | 构建流程(MSBuild) | AppVeyor(CI/CD)
  • COZE token刷新