C语言结构体变量和结构体指针详解:定义、访问、传参与易错点总结

在 C 语言中,结构体是非常重要的一种自定义数据类型。它可以把多个不同类型的数据组合到一起,用来描述一个完整的"对象"。比如学生、员工、书本等信息,都很适合用结构体来表示。

本文将从 结构体变量结构体指针 两个角度出发,系统梳理它们的定义、使用方法、区别、函数传参方式以及常见易错点,帮助你真正搞懂结构体相关知识。


一、什么是结构体

结构体(struct)是一种自定义数据类型,它允许我们把多个不同类型的数据成员组合在一起。

例如,定义一个学生信息结构体:

c 复制代码
struct Student {
    char name[20];
    int age;
    float score;
};

这个结构体中包含了:

  • name:姓名
  • age:年龄
  • score:成绩

通过结构体,我们可以更方便地管理一组相关数据。


二、结构体变量

1. 结构体变量的定义

结构体变量就是结构体类型的普通变量。

c 复制代码
struct Student s1;

这表示定义了一个 Student 类型的结构体变量 s1

2. 定义方式

方式一:先定义结构体类型,再定义变量
c 复制代码
struct Student {
    char name[20];
    int age;
    float score;
};

struct Student s1;
方式二:定义结构体类型时同时定义变量
c 复制代码
struct Student {
    char name[20];
    int age;
    float score;
} s1, s2;
方式三:使用 typedef 简化写法
c 复制代码
typedef struct Student {
    char name[20];
    int age;
    float score;
} Student;

Student s1;

这种方式更简洁,后续定义变量时可以直接写 Student s1;


三、结构体变量的成员访问

结构体变量通过 点号 . 来访问成员。

c 复制代码
s1.age = 18;
s1.score = 95.5;

如果是字符串数组成员,不能直接赋值,需要使用字符串处理函数:

c 复制代码
strcpy(s1.name, "Tom");

示例代码

c 复制代码
#include <stdio.h>
#include <string.h>

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

int main() {
    struct Student s1;

    strcpy(s1.name, "Tom");
    s1.age = 18;
    s1.score = 95.5;

    printf("name = %s\n", s1.name);
    printf("age = %d\n", s1.age);
    printf("score = %.1f\n", s1.score);

    return 0;
}

四、结构体指针

1. 什么是结构体指针

结构体指针是指向结构体变量的指针。

c 复制代码
struct Student *p;

这里 p 是一个指向 struct Student 类型的指针。

2. 初始化结构体指针

结构体指针必须指向有效内存后才能使用,常见方式有两种:

方式一:指向已有结构体变量
c 复制代码
struct Student s1 = {"Tom", 18, 95.5};
struct Student *p = &s1;
方式二:动态分配内存
c 复制代码
struct Student *p = (struct Student *)malloc(sizeof(struct Student));

使用完后要记得释放内存:

c 复制代码
free(p);
p = NULL;

五、结构体指针的成员访问

结构体指针通过 箭头 -> 访问成员。

c 复制代码
p->age = 20;
p->score = 88.5;
strcpy(p->name, "Lucy");

它等价于:

c 复制代码
(*p).age = 20;
(*p).score = 88.5;
strcpy((*p).name, "Lucy");

一般推荐直接使用 ->,更简洁可读。

示例代码

c 复制代码
#include <stdio.h>
#include <string.h>

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

int main() {
    struct Student s1 = {"Tom", 18, 95.5};
    struct Student *p = &s1;

    printf("name = %s\n", p->name);
    printf("age = %d\n", p->age);
    printf("score = %.1f\n", p->score);

    return 0;
}

六、结构体变量和结构体指针的区别

对比项 结构体变量 结构体指针
保存内容 结构体数据本身 结构体地址
成员访问 . ->
内存占用 占用整个结构体大小 只占用指针大小
传参方式 值传递,复制整个结构体 传地址,效率更高
常见用途 普通数据存储 函数参数、动态内存、数组操作

理解方式

  • 结构体变量:像一个"实体对象"
  • 结构体指针:像一个"指向对象的地址"

七、结构体作为函数参数

结构体作为函数参数有两种常见方式。

1. 传结构体变量

c 复制代码
void printStudent(struct Student s) {
    printf("%s %d %.1f\n", s.name, s.age, s.score);
}

这种方式会复制一份结构体,结构体较大时效率不高。

2. 传结构体指针

c 复制代码
void printStudent(struct Student *p) {
    printf("%s %d %.1f\n", p->name, p->age, p->score);
}

这种方式更常用,既高效,又可以修改原结构体内容。

示例:通过指针修改结构体内容

c 复制代码
#include <stdio.h>
#include <string.h>

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

void updateStudent(struct Student *p) {
    strcpy(p->name, "Alice");
    p->age = 20;
    p->score = 99.0;
}

int main() {
    struct Student s1 = {"Tom", 18, 95.5};

    updateStudent(&s1);

    printf("%s %d %.1f\n", s1.name, s1.age, s1.score);

    return 0;
}

八、结构体数组与结构体指针

结构体数组是多个结构体变量组成的数组。

c 复制代码
struct Student arr[3];

访问方式:

c 复制代码
arr[0].age = 18;
arr[1].age = 19;

如果用指针指向数组首元素:

c 复制代码
struct Student *p = arr;

则可以这样访问:

c 复制代码
p->age
(p + 1)->age

示例代码

c 复制代码
#include <stdio.h>

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

int main() {
    struct Student arr[2] = {
        {"Tom", 18, 95.5},
        {"Lucy", 20, 88.8}
    };

    struct Student *p = arr;

    printf("%s %d %.1f\n", p->name, p->age, p->score);
    printf("%s %d %.1f\n", (p + 1)->name, (p + 1)->age, (p + 1)->score);

    return 0;
}

九、常见易错点总结

1. 结构体变量不能用 ->

错误写法:

c 复制代码
s1->age = 18;

正确写法:

c 复制代码
s1.age = 18;

2. 结构体指针未初始化就使用

错误写法:

c 复制代码
struct Student *p;
p->age = 18;

此时 p 没有指向有效内存,属于野指针,容易导致程序崩溃。

正确写法:

c 复制代码
struct Student s1;
struct Student *p = &s1;
p->age = 18;

3. 字符数组成员不能直接赋值

错误写法:

c 复制代码
s1.name = "Tom";

正确写法:

c 复制代码
strcpy(s1.name, "Tom");

4. *p.age 写法错误

错误写法:

c 复制代码
*p.age

正确写法:

c 复制代码
(*p).age

或者更推荐:

c 复制代码
p->age

5. 动态分配后忘记释放内存

c 复制代码
struct Student *p = malloc(sizeof(struct Student));

使用结束后一定要释放:

c 复制代码
free(p);
p = NULL;

6. sizeof 写错对象

错误写法:

c 复制代码
malloc(sizeof(p));

sizeof(p) 只是指针大小,不是结构体大小。

正确写法:

c 复制代码
malloc(sizeof(struct Student));

十、结构体指针的本质理解

p->age 实际上等价于:

c 复制代码
(*p).age

也就是说:

  1. p 是指针
  2. *p 表示取出指针指向的结构体
  3. (*p).age 表示访问结构体成员 age

因此,-> 其实只是语法上的简写。


十一、小结

结构体变量

  • 保存的是结构体数据本身
  • 使用 . 访问成员
  • 适合普通对象使用

结构体指针

  • 保存的是结构体地址
  • 使用 -> 访问成员
  • 常用于函数传参、动态内存、数组遍历

十二、结语

结构体变量和结构体指针是 C 语言中非常基础但也非常重要的内容。

只要记住下面这几个核心点,基本就不会出错:

  • 变量用 .,指针用 ->
  • 变量存数据,指针存地址
  • 字符数组不能直接赋值,要用 strcpy
  • 指针必须先指向有效内存再使用
  • 函数传参时,传指针更高效

如果你正在学习 C 语言,建议多动手写几遍代码,尤其是"结构体变量"和"结构体指针"之间的转换,理解会更快。


相关推荐
林爷万福20 小时前
MATLAB光谱数据分析从入门到项目实战
算法·光纤光谱仪
吴可可12320 小时前
AutoCAD2016二次开发环境配置指南
算法·机器学习
Thomas_YXQ20 小时前
Unity3D Addressable 深度优化热更性能消耗
开发语言·3d·unity·微信
一条大祥脚20 小时前
ABC461 枚举|扫描线|动态前缀和|数论|dfs枚举子集
算法·深度优先
aini_lovee20 小时前
C# 快递单打印系统(万能套打系统)
开发语言·c#
计算机安禾21 小时前
【数据库系统原理】第14篇:关系模式的语义约束:函数依赖的公理系统与闭包计算
人工智能·算法·机器学习
量化君也21 小时前
快速入门量化交易都要学些什么?
大数据·人工智能·python·算法·金融
天启HTTP21 小时前
开启全局代理后网络变慢,问题出在哪
开发语言·前端·网络·tcp/ip·php
丑过三八线21 小时前
Runc 深度解析:从原理到实操
java·linux·开发语言·docker·容器·rpc