这篇博客会带你理解 顺序表初始化时“传值”与“传址”的区别,帮你避开C语言结构体操作的经典坑

 

一、先看代码:顺序表的基本结构

 

 

 

 

 

我们定义的顺序表结构体  SL  包含三个成员:

 

-  a :指向动态数组的指针

-  size :有效数据个数

-  capacity :数组的容量(可存储的最大元素数)

 

头文件  SeqList.h  中声明了初始化函数  SLInit ,注意这里最终用的是 传指针(传址) 的版本:

 

 

// SeqList.h

#define INIT_CAPACITY 4

typedef int SLDataType;

typedef struct SeqList {

    SLDataType* a; // 动态数组指针

    int size; // 有效数据个数

    int capacity; // 空间容量

}SL;

 

// 注释掉的是“传值”版本,最终用的是“传址”版本

// void SLInit(SL sl);

void SLInit(SL *ps);

 

 

二、踩坑现场:“传值”初始化为什么没用?

 

最开始我写的是 传值版本 的  SLInit ,代码长这样:

 

// 错误的“传值”初始化(已注释)

void SLInit(SL sl) {

    sl.a = NULL;

    sl.size = 0;

    sl.capacity = 0;

}

 

 

然后在  test  函数中调用:

 

SL seq_list;

SLInit(seq_list); // 直接传结构体变量(传值)

 

 

结果运行后发现  seq_list  的成员根本没被初始化——这是为什么?

 

原因是:C语言中函数参数默认是“值传递”,会拷贝一份参数的副本到函数栈帧中。

 

当我们把  seq_list  传给  SLInit  时,函数里操作的是  sl ( seq_list  的副本),而 原始的  seq_list  完全没被修改。函数执行完,副本  sl  被销毁,相当于“白忙活一场”。

 

三、正确姿势:“传址”才能真正修改结构体

 

要想修改 原始结构体变量,必须传它的 地址(指针),让函数直接操作原始变量的内存。

 

最终正确的  SLInit  是 传址版本:

 

// 正确的“传址”初始化

void SLInit(SL* ps) {

    ps->a = NULL; // 通过指针访问结构体成员(->)

    ps->size = 0;

    ps->capacity = 4; // 初始容量设为INIT_CAPACITY(4)

}

 

 

调用时传结构体的地址:

SL seq_list;

SLInit(&seq_list); // 传地址(&取地址)

 

 

此时函数里的  ps  是  seq_list  的指针,通过  ps->a 、 ps->size  访问的是 原始变量  seq_list  的内存,修改才能真正生效。

 

四、总结:传值 vs 传址的核心区别

 

方式 本质 能否修改原始变量 用法场景 

传值(SL sl) 拷贝副本 ❌ 不能 仅读取结构体内容,不修改时用 

传址(SL *ps) 操作原始变量的内存 ✅ 能 需要修改结构体时必须用 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值