原创 DeRoy 编程学习基地 2020-12-09
点击蓝字 关注我们
前言
之前有个粉丝问了我一些问题,聊天截图如下
粉丝&梦凡问题&粉丝
他的代码是这个样子的
void Pop(MazeStack* S, MSElemType e) {
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(11);
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;
}
当然,我这里少了个对指针的判断,但是这不重要,重要的是这个「过程」你明白了吗?
如果你觉得你这个理解到位了,那么你可以试着完成一下我之前发布的「图书信息管理系统」,里面都是这个操作
/*删除节点*/
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;
}
贴点代码,有兴趣去看看,今日兴趣分享blog