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 语言,建议多动手写几遍代码,尤其是"结构体变量"和"结构体指针"之间的转换,理解会更快。


相关推荐
AI人工智能+电脑小能手4 小时前
【大白话说Java面试题 第64题】【JVM篇】第24题:强引用、软引用、弱引用、虚引用分别是什么?
java·开发语言·jvm·面试
我不是懒洋洋4 小时前
从零实现Transformer:从注意力机制到ChatGPT
c语言·数据结构·c++·经验分享
yujunl4 小时前
U9的UI插件开发Card功能区上客开的按钮不能正常显示
开发语言
码界筑梦坊4 小时前
129-基于Python的城市尾气排放数据可视化分析系统
开发语言·python·信息可视化·数据分析·毕业设计
一生了无挂4 小时前
深入解析JVM、JRE与JDK:Java技术体系的核心基石
java·开发语言·jvm
m0_748839495 小时前
利用C 图形界面展示MATLAB算法的高效混合编程实践
开发语言·算法·matlab
进击的荆棘5 小时前
优选算法——哈希表
c++·算法·leetcode·哈希算法·散列表
阿牛大牛中5 小时前
阿里-RecGPT-Mobile
大数据·人工智能·算法