C语言结构体入门:定义、访问与传参全解析

在C语言中,结构体(struct)是处理复杂数据的核心工具------它能将不同类型的数据(如字符串、整数)封装成一个整体,特别适合描述真实世界中的实体(比如学生、员工、商品)。本文将通过"学生信息管理"的实例,从零讲解结构体的定义、三种访问方式,以及函数传参的两种常用形式,搭配完整代码演示,帮你快速掌握结构体核心用法。

一、结构体基础:如何定义一个"数据模板"

结构体的本质是自定义数据类型,我们先定义一个"学生"模板,包含姓名、年龄、性别、学号四个属性:

// 方式1:直接定义结构体类型

struct stu

{

char name[20]; // 姓名(字符串数组存储)

int age; // 年龄(整型)

char sex[5]; // 性别(字符串数组,兼容多字符)

char id[23]; // 学号(字符串数组,适配长学号)

};

// 方式2:用typedef给结构体起"别名"(更简洁)

typedef struct stu

{

char name[20];

int age;

char sex[5];

char id[23];

} stp1; // stp1是struct stu的别名,后续可直接用stp1定义变量

  • 关键点: typedef 的作用是简化类型名,避免每次定义变量都写 struct stu ,直接用 stp1 即可,代码更简洁(后文以别名方式为主演示)。

二、结构体变量的三种访问方式

定义结构体变量后,有三种常用方式访问其内部成员,核心区别在于是否使用指针。我们先定义变量和指针,再逐一演示:

// 定义结构体变量并初始化

stp1 st1 = {"龙傲天", 20, "男", "124124552"};

stp1* p = &st1; // 定义指针p,指向结构体变量st1的地址

  1. 直接访问:变量名.成员名(最直观)

通过"变量名 + 点号(.) + 成员名"直接访问,适合非指针场景:

printf("姓名:%s\n", st1.name); // 输出:龙傲天

printf("年龄:%d\n", st1.age); // 输出:20

printf("性别:%s\n", st1.sex); // 输出:男

printf("id:%s\n", st1.id); // 输出:124124552

  1. 解引用访问:(*指针).成员名(指针场景基础用法)

如果拿到的是结构体指针,需先通过 * 解引用获取指针指向的变量,再用点号访问成员(注意括号不能少, * 优先级低于 . ):

printf("姓名:%s\n", (*p).name); // 解引用p,等价于st1.name

printf("年龄:%d\n", (*p).age); // 输出:20

  1. 指向符访问:指针->成员名(指针场景简化用法)

C语言专门为结构体指针提供了简化语法 -> ,直接用"指针名 + -> + 成员名"访问,无需解引用,是指针场景的首选:

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

printf("年龄:%d\n", p->age); // 输出:20

三种方式效果对比

运行代码后,三种访问方式输出结果完全一致:

plaintext

姓名:龙傲天

年龄:20

性别:男

id:124124552

==========================

姓名:龙傲天

年龄:20

性别:男

id:124124552

==========================

姓名:龙傲天

年龄:20

性别:男

id:124124552

  • 总结:非指针用 变量.成员 ,指针用 指针->成员 (推荐), (*指针).成员 是等价写法但稍繁琐。

三、结构体函数传参:两种方式对比

结构体变量可作为函数参数传递,核心有两种方式:值传递和指针传递,我们通过两个函数演示差异。

  1. 指针传参:void ad1(stp1* p)

将结构体变量的地址(指针)传给函数,函数内部通过 -> 访问成员:

void ad1(stp1* p)

{

printf("姓名:%s\n", p->name);

printf("年龄:%d\n", p->age);

printf("性别:%s\n", p->sex);

printf("id:%s\n", p->id);

}

// 调用方式:传入指针p或&st1

ad1(p); // 正确

ad1(&st1); // 也正确,直接传变量地址

  1. 值传递:void ad2(stp1 st1)

将结构体变量的"副本"传给函数,函数内部通过 变量.成员 访问:

void ad2(stp1 st1)

{

printf("姓名:%s\n", st1.name);

printf("年龄:%d\n", st1.age);

printf("性别:%s\n", st1.sex);

printf("id:%s\n", st1.id);

}

// 调用方式:直接传入结构体变量

ad2(st1);

两种传参方式核心区别

传参方式 优点 缺点 适用场景

指针传递 不拷贝数据,效率高;可修改原变量 需注意指针合法性(避免野指针) 结构体较大、需修改原数据

值传递 语法简单,不影响原变量 拷贝整个结构体,占用内存多、效率低 结构体较小、无需修改原数据

传参效果演示

调用两个函数后,输出结果与直接访问一致:

plaintext

============指针传参==============

姓名:龙傲天

年龄:20

性别:男

id:124124552

==========================

姓名:龙傲天

年龄:20

性别:男

id:124124552

四、完整可运行代码(含三种访问+两种传参)

#include <stdio.h> // 包含printf函数所需头文件

// 用typedef定义结构体并起别名stp1

typedef struct stu

{

char name[20];

int age;

char sex[5];

char id[23];

} stp1;

// 指针传参函数

void ad1(stp1* p)

{

printf("姓名:%s\n", p->name);

printf("年龄:%d\n", p->age);

printf("性别:%s\n", p->sex);

printf("id:%s\n", p->id);

}

// 值传递函数

void ad2(stp1 st1)

{

printf("姓名:%s\n", st1.name);

printf("年龄:%d\n", st1.age);

printf("性别:%s\n", st1.sex);

printf("id:%s\n", st1.id);

}

int main()

{

// 定义并初始化结构体变量

stp1 st1 = {"龙傲天", 20, "男", "124124552"};

stp1* p = &st1; // 定义结构体指针

// 方式1:直接访问(变量.成员)

printf("==========直接访问==========\n");

printf("姓名:%s\n", st1.name);

printf("年龄:%d\n", st1.age);

printf("性别:%s\n", st1.sex);

printf("id:%s\n", st1.id);

// 方式2:解引用访问((*指针).成员)

printf("==========解引用访问==========\n");

printf("姓名:%s\n", (*p).name);

printf("年龄:%d\n", (*p).age);

printf("性别:%s\n", (*p).sex);

printf("id:%s\n", (*p).id);

// 方式3:指向符访问(指针->成员)

printf("==========指向符访问==========\n");

printf("姓名:%s\n", p->name);

printf("年龄:%d\n", p->age);

printf("性别:%s\n", p->sex);

printf("id:%s\n", p->id);

// 指针传参调用

printf("==========指针传参==========\n");

ad1(p);

// 值传递调用

printf("==========值传递==========\n");

ad2(st1);

return 0;

}

五、学习总结

  1. 结构体是"自定义数据类型",用于封装不同类型的关联数据,定义时可通过 typedef 起别名简化语法;

  2. 成员访问三剑客: 变量.成员 (非指针)、 (*指针).成员 (指针解引用)、 指针->成员 (指针简化,推荐);

  3. 函数传参二选一:指针传递(高效、可修改原数据)、值传递(简单、不影响原数据),优先用指针传递尤其是结构体较大时;

  4. 实操关键:初始化字符串用双引号,数组长度要预留足够空间(如姓名20位、学号23位),避免越界。

结构体是C语言面向对象编程的基础雏形,掌握它后,后续处理数组、链表、文件操作中的复杂数据会更轻松。建议多修改代码(比如添加"成绩"成员、修改传参逻辑),加深理解~

相关推荐
im_AMBER2 小时前
React 16
前端·笔记·学习·react.js·前端框架
lkbhua莱克瓦242 小时前
Java基础——常用算法5
java·开发语言·笔记·github
cs麦子2 小时前
C语言--函数(function)
c语言·开发语言
极智-9962 小时前
C语言编译器?【图文详解】Visual Studio安装配置编译运行C语言?C语言编译器下载安装?
c语言·visual studio·c语言编译器·c代码运行·visual studio下载·c编程·c语言下载
是苏浙2 小时前
零基础入门C语言之C语言实现数据结构之顺序表
c语言·开发语言·数据结构
代码雕刻家2 小时前
C语言中关于类型转换不匹配的解决方案
c语言·开发语言·算法
摇滚侠3 小时前
Spring Boot3零基础教程,响应式编程的模型,笔记109
java·spring boot·笔记
YuanDaima20484 小时前
[CrewAI] 第5课|基于多智能体构建一个 AI 客服支持系统
人工智能·笔记·多智能体·智能体·crewai
民乐团扒谱机4 小时前
实验室安全教育与管理平台学习记录(七)网络安全
学习·安全·web安全