C语言中,指针变量的坑
先看一个初始化带头结点单链表的例子,LNode是结点变量,LinkList是结点指针变量,等同于LNode*
typedef struct LNode{ // 定义单链表节点类型
int data;
struct LNode *next;
}LNode,*LinkList;
例1、错误的方法:初始化带头结点的单链表
void InitList(LinkList L)
{
L = (LinkList)malloc(sizeof(LNode));
L->data = 3;
L->next = NULL;
}
void Empty(LinkList L)
{
if(NULL == L)
{
printf("链表不存在\n");
}
else if(NULL == L->next)
{
printf("空表\n");
}
}
int main()
{
LNode p;
p.data = 2;
printf("p.data = %d\n",p.data);
LinkList L = NULL;
InitList(L);
printf("L->data = %d\n",L->data);
return 0;
}
输出结果
p.data = 2
链表不存在
例2、正确的方法:初始化带头结点的单链表
void InitList(LinkList *L)
{
(*L) = (LinkList)malloc(sizeof(LNode));
(*L)->data = 3;
(*L)->next = NULL;
}
void Empty(LinkList L)
{
if(NULL == L)
{
printf("链表不存在\n");
}
else if(NULL == L->next)
{
printf("空表\n");
}
}
int main()
{
LNode p;
p.data = 2;
printf("p.data = %d\n",p.data);
LinkList L = NULL;
InitList(&L);
printf("L->data = %d\n",L->data);
return 0;
}
输出结果
p.data = 2
空表
L->data = 3
为什么第一个 InitList(LinkList L)函数不能初始化单链表L呢?不是用的地址传递吗?
答:
问题就在于L = (LinkList)malloc(sizeof(LNode));
这里的 L 是InitList函数的形参,也就是局部变量,函数运行结束后就不存在了。
而main函数中的 L 指针变量,实际上是存储在全局变量中的,两个L不是同一个L。
例1中,main函数中的 LinkList L 一开始是指向 NULL的

从InitList(L)执行开始,虽然InitList函数中也是对L进行操作,但是此时的L 是InitList函数中的形参L ,之后的也都是对于形参的操作,如下图

例1 中传入的是LinkList 变量L,属于一级指针,不能对实参指针变量 L本身进行操作,来修改实参 L 的值,使得L指向新分配的LNode,所以实参 L 还是指向NULL,因为输出结果“链表不存在”。
例2中,传入的是LinkList 变量的指针 &L,属于二级指针,可以对实参指针变量 L 本身进行操作,来修改实参 L 的值,使得L指向新分配的LNode,(*L) = (LinkList)malloc(sizeof(LNode));
C语言中,指针变量的坑的更多相关文章
- C语言中static变量详解
Static翻译出来是“静态”“静止”的意思,在C语言中的意思其实和它的本意差不多,表示“静态”或者“全局”的意思,用来修饰变量和函数.经static修饰过后的变量或者函数的作用域或者存储域会发生变化 ...
- 关于java和c语言中,变量重名问题
请看下面的两段代码: #include <iostream>#include <cstdio>#include <cstring> using namespace ...
- C语言的指针变量
C语言的指针变量 在C语言中,变量是固定范围的存储空间,它存储的是赋给他的值, 比如: ; /* 这里是定义一个整型变量a,并把12这个值存储在a的地址空间上 这个地址空间是系统随机分配的,对用户是透 ...
- C语言_指针变量的赋值与运算,很详细
指针变量的赋值 指针变量同普通变量一样,使用之前不仅要定义说明, 而且必须赋予具体的值.未经赋值的指针变量不能使用, 否则将造成系统混乱,甚至死机.指针变量的赋值只能赋予地址, 决不能赋予任何其它数据 ...
- C语言中static修饰符的意义
在C语言中,static通常有2种含义:1)定义变量的生命周期:2)定义变量或者函数的作用域. 变量的生命周期是指,相对于程序运行的进程生命周期,变量存在的时间段.变量的生命周期由变量的存储类型(位置 ...
- 【转】C语言中,为什么字符串可以赋值给字符指针变量
本文是通过几篇转帖的文章整理而成的,内容稍有修改: 一. C语言中,为什么字符串可以赋值给字符指针变量 char *p,a='5';p=&a; //显然 ...
- C语言中,为什么字符串可以赋值给字符指针变量
转载于:http://www.cnblogs.com/KingOfFreedom/archive/2012/12/07/2807223.html 本文是通过几篇转帖的文章整理而成的,内容稍有修改: 一 ...
- (七)C语言中的void 和void 指针类型
许多初学者对C中的void 和void 的指针类型不是很了解.因此常常在使用上出现一些错误,本文将告诉大家关于void 和void 指针类型的使用方法及技巧. 1.首先,我们来说说void 的含义: ...
- 转:C语言中的static变量和C++静态数据成员(static member)
转自:C语言中的static变量和C++静态数据成员(static member) C语言中static的变量:1).static局部变量 a.静态局部变量在函数内定义,生存期为整个程序 ...
- C语言中file文件指针概念及其操作 (转载)
文件 文件的基本概念 所谓"文件"是指一组相关数据的有序集合. 这个数据集有一个名称,叫做文件名.实际上在前面的各章中我们已经多次使用了文件,例如源程序文件.目标文件.可执行文件. ...
随机推荐
- C++编译器选择是否自动生成代码的背后逻辑
C++编译器选择是否自动生成代码的背后逻辑 编译器会为class和struct(实际上两者在C++中是一回事)自动生成构造函数.赋值操作符函数和析构函数.如果不是这样,那么开发者就必须自己写一些枯燥冗 ...
- Autowired注入Service变成了biaomidou的Mapper代理
问题概述 一个Springboot工程,使用Mybatis-plus作为数据层框架 使用@MapperScan注解扫描Mapper接口 @MapperScan("org.net5ijy.cl ...
- SV Interface and Program
内容 验证平台与待测设计的连接 VTB driver和dut之间的连线通过tb中声明wire连线 通过例化dut的方式进行连接 A module的input连接到B module的output SVT ...
- 【MicroPython】要是找不到某个函数的定义,可能是做了宏转换
转换宏 map查找接口
- 【css】 text-align 居中导航
原理 :利用 inline-block 将 导航 作为 文本 , 被外层具有 text-align 属性的导航盒子包含 .从而实现居中效果 1. html 结构 <header> < ...
- [转帖]Docker最佳实践:5个方法精简镜像
https://juejin.cn/post/6844903880526921741 精简Docker镜像的好处很多,不仅可以节省存储空间和带宽,还能减少安全隐患.优化镜像大小的手段多种多样,因服 ...
- [转帖]UTF8 和 AL32UTF8 的区别
本文章向大家介绍UTF8 和 AL32UTF8 的区别,主要内容包括 .使用实例.应用技巧.基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下. UTF8 和 AL32UTF8 ...
- Linux上面批量更新SQLSERVER SQL文本文件的办法
1. 今天同事让帮忙更新几个SQL文件.. 本着自己虽然low 但是不能太low的想法, 简单写一个 shell 脚本来执行. 2. 因为我的linux 里面都安装了 sqlcmd 的工具 所以办法就 ...
- 冷备份MySQL数据库并且使用Docker直接运行的操作过程
备份数据库 查看数据库的数据文件的位置 systemctl status mysqld 查看启动进程以及防水 /etc/my.conf 查看datadir 指向Mysql数据库的存储数据路径. 关闭数 ...
- 每日一道Java面试题:方法重载与方法重写,这把指定让你明明白白!
写在开头 请聊一聊Java中方法的重写和重载? 这个问题应该是各大厂面试时问的最多的话题之一了,它们几乎贯穿了我们日常的开发工作,在过往的博客中我们多多少少都提到过重载与重写,而今天我们就一起来详细的 ...