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

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.dtcms.com/a/277213.html

相关文章:

  • 【Python】venv:配置独立镜像源
  • 常用的docker命令备份
  • 007_用例与应用场景
  • python 列表(List) vs. 元组(Tuple):什么时候该用不可变的元组?它们在性能和用途上有什么区别?
  • 暑期自学嵌入式——Day01(C语言阶段)
  • 协程的基本使用
  • 【保姆级图文详解】MCP架构(客户端-服务端)、三种方式使用MCP服务、Spring AI MCP客户端和服务端开发、MCP部署方案、MCP安全性
  • 基于 CentOS 7 的 LVS+DR+Web+NFS 旅游攻略分享平台部署
  • CentOS系统下前后端项目部署攻略
  • 从 Manifest V2 升级到 Manifest V3:常见问题与解决方案
  • vue-component
  • [Linux入门 ] RAID存储技术概述
  • (S4)Efficiently Modeling Long Sequences with Structured State Spaces论文精读(逐段解析)
  • [Rust 基础课程]Hello World
  • 数据结构 单链表(2)--单链表的实现
  • 聊一聊Java生态接口测试常见的框架
  • 在 Spring Boot 中使用 MyBatis 的 XML 文件编写 SQL 语句详解
  • MySQL SQL语句精要:DDL、DML与DCL的深度探究
  • Design Compiler:什么是代价函数(Cost Function)
  • HarmonyOS组件/模板集成创新活动-元服务小云体重管理引入案例(步骤条UI组件)
  • python赤道上空的大气环流剖面图(纬向-高度剖面)
  • 多级@JsonTypeInfo和@JsonSubTypes注解使用详解及场景分析
  • 剑指offer59_翻转单词顺序
  • Redis 命令总结
  • Docker三剑客
  • Docker 基于 Cgroups 实现资源限制详解【实战+源码】
  • 从一个想法到一套软件——我的AI质检平台设计蓝图
  • 03.Python 字符串中的空白字符处理
  • 【爬虫】02 - 静态页面的抓取和解析
  • HTTP与HTTPS详解