指针做形参时要注意的一个地方

本文探讨了C语言中链表删除节点的问题,通过对比两种不同的实现方式,解释了如何正确地更新指向被删除节点数据的指针,并分析了指针操作的细节。
Linklist deleteNode(Linklist head, Linklist toDelete, type *data)
{
Linklist temp = head;
if(temp->Next != toDelete)
{
temp = temp->Next;
}

data = &(temp->Next->data);
temp->Next = temp->Next->Next;
free(toDelete);

return temp->Next;

}

上面这段程序在main()中由以下语句调用:

type deleteData = 1;

head = deleteNode(head, NODE, &deleteData);
printf("%d\n", deleteData);

调用后发现发现deleteData的值始终是1!


于是将代码改为

Linklist deleteNode(Linklist head, Linklist toDelete, type *data)
{
Linklist temp = head;
if(temp->Next != toDelete)
{
temp = temp->Next;
}

(*data) = temp->Next->data;
temp->Next = temp->Next->Next;
free(toDelete);

return temp->Next;

}

这样deleteData的值就会变成temp->Next->data的值了!

原来deleteNode(Linklist head, Linklist toDelete, type *data)函数是用一个四字节的内存存放了deleteData的地址,也就是形参data,第一段代码中语名data = &(temp->Next->data);的作用是将该内存的内容改成了temp->Next->data的地址,而跟deleteData变量没有任何关系!

而后面那段代码中的语句(*data) = temp->Next->data;则是将该内存里面的地址所指的变量(也就是deleteData)的值改成temp->Next->data,这显然是对的!

<think>嗯,用户问的是关于形参含有指针的函数调用完后指针指向的问题。这需要仔细分析指针在函数调用中的传递方式,尤其是按值传递和按引用传递的区别。首先得回顾指针作为函数参数的机制,指针本身是一个变量,存储的是地址,当它作为参数传递给函数,实际上是传递了地址的副本。 接下来要考虑函数内部对指针的操作,比如解引用修改指向的内容,还是修改指针本身指向的地址。如果是前者,那么原指针指向的内容会被改变,因为通过副本地址访问的是同一块内存。但如果是后者,比如在函数内部让指针指向其他地方,由于传递的是副本,原指针的指向不会改变。 然后需要举例子说明这两种情况,比如swap函数修改值和修改指针本身的例子。可能用户容易混淆这两种情况,所以得明确区分。同注意到,如果形参指针指针或者指针的引用,那修改指针的指向会影响原指针,但这种情况属于更深一层的间接引用,可能需要进一步解释。 另外,用户可能在实际编程中遇到这类问题,比如在函数内部分配内存并期望指针在函数外生效,这候如果没有使用指针指针或引用,就会导致内存泄漏或者指针未改变的情况。所以需要提醒正确的方法,比如使用二级指针或者返回指针。 最后,要确保回答结构清晰,分点说明不同情况,并给出示例代码,帮助用户理解。同要检查术语是否正确,避免误导,比如强调“按值传递”和“按引用传递”在C中的不同实现方式(C没有引用,但C++有,所以可能需要根据用户使用的语言调整说明)。</think>关于形参指针的函数调用后指针指向问题,分步骤说明如下: 一、基本机制 1. 指针参数传递本质是值传递:传递的是指针变量存储的地址值的副本 2. 函数内部操作分两种情况: - 通过解引用(*)修改指针指向的内存内容 - 修改指针本身存储的地址值 二、示例分析(以C语言为例) 1. 修改内存内容的情况: ```c void modifyContent(int* p) { *p = 100; // 修改指针指向的内存 } int main() { int a = 10; int* ptr = &a; modifyContent(ptr); // 此ptr仍指向a,但a的值变为100 } ``` 2. 修改指针指向的情况: ```c void changePointer(int* p) { int b = 200; p = &b; // 修改的是指针的副本 } int main() { int a = 10; int* ptr = &a; changePointer(ptr); // ptr仍指向a,函数内的修改不影响原指针 } ``` 三、关键结论 1. 函数内修改指针指向: - 仅影响形参副本的指向 - 不会改变实参指针的原始指向 2. 函数内修改指向内容: - 通过解引用操作会影响原始数据 - 因为所有副本指针都指向同一内存区域 四、特殊处理技巧 若需要改变指针的指向,需使用二级指针: ```c void realChange(int** pp) { static int b = 200; *pp = &b; // 通过二级指针修改原始指针的指向 } int main() { int a = 10; int* ptr = &a; realChange(&ptr); // 此ptr指向b } ``` 五、注意事项 1. 函数返回后局部变量指针会失效(如非静态局部变量) 2. 动态内存分配的情况需要特别处理: - 在函数内malloc分配的内存 - 需要通过指针参数正确返回地址 - 注意内存泄漏问题 理解这些原理可避免以下常见错误: 1. 误以为修改指针形参会影响实参 2. 未正确初始化指针导致访问非法内存 3. 对已释放内存区域的非法访问
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值