xxl-job 执行结果是空_空指针,段错误,这场面试我栽倒在这里了!
空指针,段错误,这场面试我栽倒在这里了!
NULL在C/C++中的标准定义
NULL的标准定义
#if !defined(NULL) && defined(__NEEDS_NULL)
#ifdef _cplusplus
#define NULL 0 // 这里对应C++的情况
#else
#define NULL (void *)0 // 这里对应C语言的情况
#endif
编译器预先定义了一个宏_cplusplus
,来判断当前的编译环境是C++的还是C语言的,在C++定义为0,在C语言中定义为(void *)0
。
在C/C++中的区别
在C语言中,C中的“标准”写法,NULL被替换为一个void*
类型的指针右值,值等于0;由于是void* 类型,可以隐式转化为其它类型的指针。
在C++中,void* 无法自由隐式转换为其它类型的指针,而字面量0可以隐式转换为指针类型。
NULL 的本质是什么
我们从指针,空指针,空指针常量以及指向的内存说起
从指针角度来看
我们看以下定义,p是一个函数内的局部变量,则p的值是随机的,也就是说p是一个野指针。
int func()
{int *p; ...
}
再看以下函数,p是一个局部变量,分配在栈上的地址,p的值是(void *)0
,实际就是0x00000000
,意思就是指针p指向内存的0x00000000
地址处。这时候p就不是野指针了。
int func()
{int *p = NULL; ...
}
什么是空指针(null pointer)?
如果将空指针常量转换为指针类型,则保证生成的指针(称为空指针)将不相等的值与指向任何对象或函数的指针进行比较。
定义char *p=0
后,在之后p的任何一种赋值操作之后,p 都成为一个空指针,即p不指向任何实际的对象或者函数。反过来说,任何对象或者函数的地址都不可能是空指针。
什么是空指针常量(null pointer constant)?
值为0的整数常量表达式,或强制转换为void *
类型的表达式,称为空指针常量
空指针(null pointer)指向了哪里的内存
这里标准没有定义,取决于系统的实现。我们常见的空指针一般指向0x00000000
地址,即空指针的内部用全0x00000000
来表示,也有一些系统用一些特殊的地址值或者特殊的方式表示空指针。
在我们实际写代码时,关键点在于判断哪个是空指针。
NULL 有什么作用
在大部分的CPU中,内存的0x00000000
地址处都不是可以随便访问的,所以野指针指向了这个区域可以保证野指针有个安家之所,否则会发生段错误。
当你尝试访问的时候会阻止你,但是有些地址不是只读的,如果一个指针指向了这个地址,你又在不经意间修改了它,可能会导致一些重要的文件被修改,所以指针初始化成NULL是有必要的。
注意不要混用'0' 和 '0' 和 0 和 NULL
- '0'是一个转义字符,他对应的ASCII编码值是0,本质就是0;常用于表示字符串的结尾标志,以判断字符串有没有到头。
- '0'是一个字符,他对应的ASCII编码值是48,本质是48。
- 0是一个int类型的数字,本质就是0。
- NULL是一个表达式,是强制类型转换为
void *
类型的0,一般用来比较指针是否是一个野指针。
NULL是不是0呢
NULL 就是0?
我们先来看以下代码:
//https://tool.lu/coderunner/
#include<stdio.h>
int main()
{ int *p=NULL; printf("%s",p);
}
结果如下:
输出(null) ,在执行int *p=NULL
,打印出来空白,实际上p的值为0x00000000
,在C语言中,NULL的本质是0,但是这个0不是当一个整形数据来解析,而是当一个内存地址来解析的,代表的是内存的0地址。
(void *)0
这个整体表达式表示一个指针,地址在哪里取决于指针变量本身,这个指针变量指向0地址(实际是0地址开始的一段内存)。
NULL 不是0?
如果一个指针被赋予NULL,相当于这个指针执行了0x00000000
这个逻辑地址,但是在C语言中0x0000这个逻辑地址用户是不能使用的,所以当你试图取一个指向了NULL的指针的内容时,就会提示段错误,测试一下代码如下:
//https://tool.lu/coderunner/
//来源:技术让梦想更伟大
//作者:李肖遥
#include<stdio.h>
int main()
{ int *node = NULL;int p = 0;p = *node;printf("%dn",p);return 0;
}
编译结果如下:
由于指针node执行的是NULL,也就是逻辑地址0x00000000
,而这个地址不能访问,所以编译器提示段错误。
那么看到这里你觉得NULL还是0吗?根据宏定义我们知道:(void *)0
表示把数值0强制转换为void *
类型,所以最后运行结果为0。
变量在定义时,系统会给他分配内存空间,指针变量也是一样,如果指针没有指向的话,那么地址就是随机值,如果不小心用的话就会导致数据错误,从而使程序退出。
NULL 使指针p指向地址0x00000000
,在大多数系统中都将0x00000000
作为不被使用的地址,所以运用p也不会毁坏数据。
但也有系统会使用地址0x00000000
,而将 NULL 定义为其他值,所以不要把 NULL 和 0 等同起来。
我们使用值传递的方式来看,在网上有一个面试题,这里我参考一下代码,能够帮助大家更好的理解,其代码如下:
//https://tool.lu/coderunner/
//来源:技术让梦想更伟大
//作者:李肖遥
#include <stdio.h>void vPassByFun(int *node)
{static int N = 1024;node = &N;
}int main()
{int *node = NULL;int p = 0;vPassByFun(node);p = *node;printf("%dn",p);return 0;
}
输出结果如下:
vPassByFun函数
是值传递,node指针变量的值并不受影响,所以这个程序的效果和上一个程序运行结果都是段错误。
如果要让结果为1024,应该怎样写代码呢?我们来这样写代码:
//https://tool.lu/coderunner/
//来源:技术让梦想更伟大
//作者:李肖遥
#include <stdio.h>void vPassByFun(int ** node)
{static int N = 1024;*node=&N;
}int main()
{int *node = NULL;int p = 0;vPassByFun(&node);p = *node;printf("%dn",p);return 0;}
运行结果如下:
传递一个二级指针也就是传递node指针变量的指针给vPassByFun函数
,这样的话结果就对了。
最后
编码过程中,我们需要对自己的指针负责,往往导致bug出现或者找不到问题所在地的就是这种细节。最后,原创不易,希望能够改正文章的错误,多提意见留言,谢谢。
xxl-job 执行结果是空_空指针,段错误,这场面试我栽倒在这里了!相关推荐
- 空指针,段错误,这场面试我栽倒在这里了!
作者 | 李肖遥 来源 | 技术让梦想更伟大(ID:gh_f7effb2fbc1c) 面试官:满头的汗的,来面试的路一定很远吧? 还好还好,骑车不到俩小时 面试官:来先喝杯水,咱们面试不急,边喝边聊 ...
- linux进程的堆栈空间_代码段(指令,只读)、数据段(静态变量,全局变量)、堆栈段(局部变量)、栈【转】...
转自:http://blog.csdn.net/gongweijiao/article/details/8207333 原文参见:http://blog.163.com/xychenbaihu@yea ...
- java数据段 静态区_linux进程的堆栈空间_代码段(指令,只读)、数据段(静态变量,全局变量)、堆栈段(局部变量)、栈【转】...
一)概述 .堆栈是一个用户空间的内存区域,进程使用堆栈作为临时存储. .堆栈中存放的是函数中的局部变量,在函数的生命周期中可以将变量压入堆栈,编译器需要确保堆栈指针在函数退出前恢复到初始位置,也就是说 ...
- python判断队列是否为空_[python模块]队列queue
一.队列queue 队列queue 多应用在多线程场景,多线程访问共享变量. 对于多线程而言,访问共享变量时,队列queue的线程安全的. 因为queue使用了一个线程锁(pthread.Lock() ...
- ie 不执行回调函时_「Excel VBA操作IE篇」10分钟内设置完成,3句代码打开IE浏览器
大家好,我是咚腔! Excel VBA还可以 操作IE浏览器,有没有搞错? 没错,可以操作,而且非常好用.因为Excel有强大的数据分析功能. 这有什么关系?关系很大. 现在是数据时代,定期数据获取以 ...
- java 主动抛出 段错误_段错误产生的原因~
原文:https://blog.csdn.net/qq_29350001/article/details/53780697 一.什么是段错误? 一旦一个程序发生了越界访问,cpu 就会产生相应的保护, ...
- 程序员打字练习_程序员必须来看的面试圣经!!
当我最初开始参加编程面试的时候,我所有最心仪的公司都忽视了我.现在回头看那个时候,我发现自己当时去参加面试都完全没做任何准备.虽然已经有许多博客文章和书籍在讲编程面试,但现在的我作为面试官,坐在桌子的 ...
- Rust语言——无虚拟机、无垃圾收集器、无运行时、无空指针/野指针/内存越界/缓冲区溢出/段错误、无数据竞争...
2006年,编程语言工程师Graydon Hoare利用业余时间启动了Rust语言项目.该项目充分借鉴了C/C++/Java/Python等语言的经验,试图在保持良好性能的同时,克服以往编程语言所存在 ...
- java如何创造一个整数的类_【技术干货】Java 面试宝典:Java 基础部分(1)
原标题:[技术干货]Java 面试宝典:Java 基础部分(1) Java基础部分: 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语法,集合的语法,io 的 ...
最新文章
- oracle io profile,ORACLE 中 PROFILE的管理
- 【Flutter】Flutter 启动白屏问题 ( 问题描述 | 在 launch_background.xml 中设置启动过渡 UI )
- 【张其中】中本聪,我们究竟需要怎样的加密货币?
- 陕西国防 c语言第三章实训三答案,C语言程序设计(上)
- 4 微信公众号开发 被动回复消息 回复没有反应怎么办
- .net remoting 技术
- LeetCode 1673. 找出最具竞争力的子序列(单调栈)
- 怎样查看cudnn版本_tensorflowGPU版本踩坑记录
- allegro中焊盘的设置
- Android 系统性能优化(38)---Android内存优化之二:MAT使用进阶
- easyicon-----一个非常好用的找图标的网站
- EdrawMax Crack,多合一的图表应用程序
- Excel数据分析项目——电商数据分析实战
- 使用HBuilder将web项目打包成app
- VRPN-OSVR介绍
- 计算机十进制数中码数有几个,计算机中的数和码
- 计算雅思成绩C语言,雅思成绩到底如何计算的?
- 人工智能领域数据标注行业的核心需求痛点
- python解压zip_用Python处理ZIP压缩包
- 计算机水平每分钟多少字,电脑打字每分钟打多少在一才算快啊? 一般拼音打字一分钟多少才算可以?...