来源:微信公众号「编程学习基地」
前言
之前有个粉丝问了我一些问题,聊天截图如下
问题&粉丝
他的代码是这个样子的
void Pop(MazeStack* S, MSElemType e) {
LinkType p;
if (S->size == 0)
exit(0);
e = S->top->data;
***
***
}
一些不必要的代码我省略了,大意就是通过传参获取栈顶元素,然后一直拿不到数据。
这种错误我想如果不熟悉C语言的新手都会犯,基础不牢地动山摇
答疑&梦凡
我们C语言学指针那一章都先学swap函数实现交换两个变量的值的功能,你还记得吗?
void swap(int *a,int *b){
int temp = *a;
*a = *b;
*b = temp;
}
在函数体内交换两个变量的值为什么要传指针?
因为函数调用传递实参,函数体内通过形参拷贝实参数据,并且形参只在函数体内存在,出了函数就被释放掉了
那么同样的道理,你传个变量就想获取栈顶元素无异于痴人说梦,解决办法当然是传指针咯
那么关于指针传参这一块,又有讲究,那么从一道面试题讲起…
面试题
先看题,题目很简单,但是你知道答案吗?
/*
*
* 修改程序, 使得程序正常输出 1234567890
*
*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void ApplyMemory(char* p)
{
p = (char*)malloc(10);
}
int main()
{
char* val = NULL;
ApplyMemory(val);
strcpy(val, "1234567890");
printf("%s", val);
free(val);
return 0;
}
现在我们有了前面的指针铺垫,那么你能正确修改程序吗?
我非常明确的告诉你不只是更改申请内存的大小为11(’\0’需要一个字节)
这个时候你可能就会想起函数里面申请一块内存之后需要通过返回值返回申请内存地址
修改1:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
char* ApplyMemory()
{
char* p = (char*)malloc(10);
return p;
}
int main()
{
char* val = NULL;
val = ApplyMemory();
strcpy(val, "1234567890");
printf("%s", val);
free(val);
return 0;
}
嗯,没问题,正确打印1234567890
那么这个时候面试官又问了,如果不通过函数返回值,你可不可以拿到申请的内存地址?
思考良久,怀疑人生,情绪奔溃…
其实很简单嘛,你把 *p
当成一个值,那么像交换函数一样,传递这个值的指针,问题不就解决了吗?
这个时候一直无人问津的二级指针跳了出来,你知不知道,我很重要
。
修改2:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void ApplyMemory(char** p)
{
(*p) = (char*)malloc(11);
}
int main()
{
char* val = NULL;
ApplyMemory(&val);
strcpy(val, "1234567890");
printf("%s", val);
free(val);
return 0;
}
当然,我这里少了个判断p是否为空,但是这不重要,重要的是这个过程你明白了吗?
如果你觉得你这个理解到位了,那么你可以试着完成一下我之前发布的图书信息管理系统,里面都是这个操作
/*删除节点*/
int deroy_list_delete(deroy_list_t** list_head, int num)
{
int counter = 1;
deroy_node_pt current = NULL;
deroy_node_pt tmp = NULL;
if (list_head == NULL || *list_head == NULL || (*list_head)->limit_size <= 0)
{
errno = EINVAL;
exit(errno);
}
current = (*list_head)->head;
while (counter < num)
{
counter++;
current = current->next;
}
if (counter == 1)
{
/*头删*/
tmp = (*list_head)->head;
(*list_head)->head = (*list_head)->head->next;
free(tmp);
tmp = NULL;
(*list_head)->limit_size--;
return 0;
}
if ((*list_head)->limit_size == counter)
{
/*尾删*/
tmp = (*list_head)->tail;
(*list_head)->tail = (*list_head)->tail->prev;
free(tmp);
tmp = NULL;
(*list_head)->tail->next = NULL;
(*list_head)->limit_size--;
return 0;
}
tmp = current;
current->prev->next = current->next;
current->next->prev = current->prev;
free(tmp);
tmp = NULL;
(*list_head)->limit_size--;
return 0;
}
贴点代码,有兴趣去看看