C语言结构体指针详解:语法、成员访问与函数传参

陆遥
陆遥
发布时间:2026-10-14 | 3人浏览过
原创

结构体指针是C语言中操作复杂数据结构的核心工具。通过指针直接访问内存地址,不仅能实现高效的成员访问(使用->运算符),还能避免函数传参时的数据拷贝开销。

结构体指针的定义与赋值规则

指针可以指向一个结构体,定义形式通常为:struct 结构体名 *变量名;。在定义结构体变量的同时,也可以直接定义指向该结构体的指针。

以下示例展示了如何定义学生信息结构体并初始化指针:

#include <stdio.h>

// 定义结构体类型,同时定义实例stu1和指针pstu
struct stu {
    char *name; // 姓名
    int num;    // 学号
    int age;    // 年龄
    char group; // 所在小组
    float score;// 成绩
} stu1 = { "Tom", 12, 18, 'A', 136.5 }, *pstu = &stu1;

需要特别注意区分结构体类型与结构体变量的概念。结构体本身仅是一种数据类型模板(类似 int),编译器不会为其分配内存空间;只有结构体变量才包含实际数据并占用内存。

  • 正确做法:取结构体变量的地址。struct stu *pstu = &stu1;
  • 错误做法:直接对类型名或变量名不加 & 赋值给指针。struct stu *pstu = stu1; 会导致编译错误。
  • 无效做法:试图获取不存在的“结构体名”的地址。struct stu *pstu = &stu; 是非法的。

获取结构体成员的方法

通过结构体指针访问成员时,主要有两种等效的写法:

  1. 解引用加点运算:(*pointer).memberName。由于成员访问运算符 . 的优先级高于解引用运算符 *,因此必须使用括号将 *pointer 括起来。如果去掉括号写成 *pointer.memberName,则会被解释为 *(pointer.memberName),导致逻辑完全错误。
  2. 箭头运算符:pointer->memberName。这里的 -> 称为“箭头”,是专门用于结构体指针访问成员的新增运算符。这种写法更加直观且常用。

【示例】读取结构体成员的值:

printf("%s的学号是%d,年龄是%d,在%c组,今年的成绩是%.1f!\n", 
       (*pstu).name, (*pstu).num, (*pstu).age, (*pstu).group, (*pstu).score);
printf("%s的学号是%d,年龄是%d,在%c组,今年的成绩是%.1f!\n", 
       pstu->name, pstu->num, pstu->age, pstu->group, pstu->score);

结构体指针处理数组

当处理结构体数组时,结构体数组名即为首元素的地址。利用指针遍历可以避免索引运算的繁琐,提升代码的可读性。

【示例】遍历全班学生信息:

#include <stdio.h>

struct stu {
    char *name;
    int num;
    int age;
    char group;
    float score;
};

struct stu stus[] = {
    {"Zhou ping", 5, 18, 'C', 145.0},
    {"Zhang ping", 4, 19, 'A', 130.5},
    {"Liu fang", 1, 18, 'A', 148.5},
    {"Cheng ling", 2, 17, 'F', 139.0},
    {"Wang ming", 3, 17, 'B', 144.5}
}, *ps;

int main() {
    // 计算数组元素个数
    int len = sizeof(stus) / sizeof(struct stu);
    
    printf("Name\tNum\tAge\tGroup\tScore\n");
    // 指针逐位移动遍历
    for (ps = stus; ps < stus + len; ps++) {
        printf("%s\t%d\t%d\t%c\t%.1f\n", ps->name, ps->num, ps->age, ps->group, ps->score);
    }
    return 0;
}

作为函数参数传递的优势

如果不使用指针,而是直接将结构体变量作为参数传递给函数,C语言会将整个结构体所有成员复制到栈空间中。如果结构体包含大量数据或嵌套数组,这会带来显著的时间和空间开销。

使用结构体指针作为参数传递时,实参只向形参传输一个内存地址,效率极高。

【示例】计算学生总成绩、平均分及低于特定分数的人数:

#include <stdio.h>

struct stu {
    char *name;
    int num;
    int age;
    char group;
    float score;
}stus[] = {
    {"Li ping", 5, 18, 'C', 145.0},
    {"Zhang ping", 4, 19, 'A', 130.5},
    {"He fang", 1, 18, 'A', 148.5},
    {"Cheng ling", 2, 17, 'F', 139.0},
    {"Wang ming", 3, 17, 'B', 144.5}
};

// 函数声明:接收结构体指针和长度
void average(struct stu *ps, int len);

int main() {
    int len = sizeof(stus) / sizeof(struct stu);
    average(stus, len);
    return 0;
}

void average(struct stu *ps, int len) {
    int i, num_140 = 0;
    float sum = 0;
    
    for(i=0; i<len; i++) {
        // 利用算术运算移动指针 (ps + i)
        sum += (ps + i)-> score;
        if((ps + i)->score < 140) num_140++;
    }
    
    printf("sum=%.2f\naverage=%.2f\nnum_140=%d\n", sum, sum/5, num_140);
}

以上就是结构体和指针的详细内容,更多关于C语言基础的知识资料请关注本站其它相关文章!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表