C/C++结构体成员访问:变量与指针的两种操作方式

2026-09-01 20:22:29 9 次阅读

C/C++结构体是程序开发中非常常见的数据组织方式,它可以将多个不同类型的数据组合成一个完整的数据对象。在实际编码过程中,开发者经常需要访问结构体中的成员变量,而根据结构体对象的类型不同,成员访问方式也有所区别。

C/C++中结构体成员访问主要分为两种情况:通过结构体变量访问成员,以及通过结构体指针访问成员。理解这两种访问方式的区别,是掌握结构体操作、指针使用以及内存管理的重要基础。

结构体变量访问成员:使用点运算符(.)

当定义一个结构体变量后,可以直接通过点运算符(.)访问其中的成员。

例如:

#include 

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

int main() {
    struct Student stu;

    stu.age = 18;
    stu.score = 95.5;

    printf("年龄:%d
", stu.age);
    printf("成绩:%.1f
", stu.score);

    return 0;
}

代码中定义了一个 Student 结构体,包含姓名、年龄和成绩三个成员。创建结构体变量 stu 后,可以直接通过:

stu.age
stu.score

的形式访问对应成员。

这种访问方式适用于结构体对象本身存在于当前作用域中的情况,例如:

  • 局部结构体变量;

  • 全局结构体变量;

  • 作为函数参数传递的结构体对象。

点运算符的本质是根据结构体变量的地址定位成员所在的内存区域,然后进行数据读取或修改。

结构体指针访问成员:使用箭头运算符(->)

当使用指针保存结构体地址时,不能直接通过点运算符访问成员,而需要使用箭头运算符(->)。

示例:

#include 

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

int main() {
    struct Student stu;
    struct Student *p;

    p = &stu;

    p->age = 20;
    p->score = 88.5;

    printf("年龄:%d
", p->age);
    printf("成绩:%.1f
", p->score);

    return 0;
}

这里定义了结构体指针:

struct Student *p;

然后通过取地址操作符:

p = &stu;

让指针指向结构体变量 stu

之后可以通过:

p->age
p->score

访问结构体成员。

箭头运算符实际上是点运算符和指针解引用操作的组合:

p->age

等价于:

(*p).age

也就是说,程序会先通过 *p 获取指针指向的结构体对象,然后使用点运算符访问成员。

点运算符与箭头运算符的区别

虽然两种方式最终都是访问结构体成员,但使用场景存在明显区别。

访问方式操作符操作对象示例
结构体变量访问.结构体对象stu.age
结构体指针访问->结构体地址p->age

简单来说:

  • 有结构体变量,用 .

  • 有结构体指针,用 ->

这是C/C++结构体成员访问中最基本的规则。

为什么结构体指针更常用于函数传递

在实际项目开发中,经常需要将结构体传递给函数。如果直接传递结构体变量,会复制整个结构体数据。

例如:

void printStudent(struct Student stu)
{
    printf("%d", stu.age);
}

调用函数时:

printStudent(stu);

会产生一次结构体复制。

如果结构体包含大量成员,这种复制会增加内存开销。

更常见的方式是传递结构体指针:

void printStudent(struct Student *p)
{
    printf("%d", p->age);
}

调用:

printStudent(&stu);

这种方式只传递结构体地址,不需要复制完整数据,因此效率更高。

在大型项目、操作系统开发、嵌入式程序以及C++底层开发中,结构体指针的使用非常普遍。

动态创建结构体与成员访问

C语言中可以通过动态内存分配创建结构体对象,此时通常需要使用结构体指针访问成员。

示例:

#include 

struct Student {
    int age;
};

int main()
{
    struct Student *p;

    p = (struct Student *)malloc(sizeof(struct Student));

    if (p != NULL) {
        p->age = 22;
    }

    free(p);

    return 0;
}

通过 malloc 分配内存后,返回的是一块内存地址,因此必须使用指针保存。

此时:

p->age

是访问动态结构体成员的标准方式。

使用动态结构体时需要注意:

  1. 检查 malloc 是否成功;

  2. 使用完成后及时调用 free 释放内存;

  3. 避免访问已经释放的结构体指针。

C++中的结构体成员访问

C++中的 struct 与 C语言类似,也支持两种成员访问方式。

例如:

#include 
using namespace std;

struct Person {
    string name;
    int age;
};

int main()
{
    Person person;

    person.name = "Tom";
    person.age = 25;

    Person *ptr = &person;

    cout << ptr->name << endl;
    cout << ptr->age << endl;

    return 0;
}

C++中的结构体不仅可以包含数据成员,还可以包含成员函数,因此访问方式也更加灵活。

例如:

struct Person {
    int age;

    void show()
    {
        cout << age;
    }
};

对象调用成员函数:

person.show();

指针调用成员函数:

ptr->show();

两者遵循相同的成员访问规则。

常见错误分析

错误一:使用点运算符访问结构体指针

错误代码:

struct Student *p;

p.age = 18;

编译器会报错,因为 p 是地址,不是结构体对象。

正确写法:

p->age = 18;

或者:

(*p).age = 18;

错误二:结构体指针未初始化

错误代码:

struct Student *p;

p->age = 20;

此时 p 没有指向有效内存,访问成员可能导致程序崩溃。

正确方式:

struct Student stu;
struct Student *p = &stu;

p->age = 20;

或者:

struct Student *p = malloc(sizeof(struct Student));

错误三:忘记释放动态内存

动态创建结构体后:

struct Student *p = malloc(sizeof(struct Student));

使用结束后应该:

free(p);

否则可能造成内存泄漏。

结构体成员访问的实际应用场景

结构体变量和结构体指针在不同领域都有广泛应用。

数据封装

结构体可以将多个相关数据组合,例如:

  • 学生信息;

  • 用户数据;

  • 网络数据包;

  • 配置参数。

链表实现

C语言链表节点通常通过结构体指针连接:

struct Node {
    int data;
    struct Node *next;