C语言中的"NULL"到底是什么?又不是什么?有什么用?怎么用?
2016-06-17 20:02
429 查看
转自:http://blog.csdn.net/fovwin/article/details/8057854
这个问题其实困扰我很久了,我问很多人"NULL"是什么?有啥用?
大多数人的回答是:"NULL就是系统定义特殊的0,把你初始化的指针指向它,可以防止“野指针”的恶果。"
今天碰到一个C语言的笔试题,还是一道不错的题~~~
Exp 1:
[cpp] view
plain copy
#include <stdio.h>
void fun(int *node)
{
static int N=100;
node=&N;
}
int main()
{
int *node=NULL;
int a=0;
fun(node);
a=*node;
printf("%d\n",a);
return 0;
}
请回答,以上这题的输出结果啥?
从结果中,这题可以区别出对C语言掌握的几个程度。那结果是:100?0?段错误退出?哪一句导致的?为什么?
认为是第一个结果人其实是被static这个关键词欺骗的,但是static是对N的修饰,表示对N的改变不会在fun函数的‘}’之后被释放掉~~~还有一个点就是:C语言的函数永远是值传递(除了数组,呵呵~~~),所以你想改变指针的指向(地址值),就必须传递指针的指针,除非你用return~~~
认为是第二个结果的人掌握了第一个结果的点,并且知道在C语言里是那样定义NULL的:
[cpp] view
plain copy
#undef NULL
#if defined(__cplusplus)
#define NULL 0
#else
#define NULL ((void *)0)
#endif
但是gcc下发现却是段错误退出了~~~
问题在这句:
[cpp] view
plain copy
a=*node;
[cpp] view
plain copy
/*对node进行*运算,node此时木有改变的,还是(void *)0指针~~~所以段错误就出来,当然你可以读取NULL本身的值,即0,但是读取它指向的值,那是非法的,会引发段错误(貌似这种指针的错误还有:操作系统限制用户访问的地址空间,内存木有分到的地址空间(几百KB的嵌入式系统中普遍存在),再加这种就有三种,当然野指针也可能乱指到一般用户合法的地址,然后就乱改,然后就失控了~~~)*/
NULL是个好东西,给一出生的指针一个安分的家~~~
ps:我一开始就以为是0,功力不深啊~~~修炼,修炼~~~
Exp 2:
[cpp] view
plain copy
#include <stdio.h>
int main(...)
{
int *iPtr1 = NULL;
int *iPtr2 = 0;
//error: invalid conversion from `int' to `int*'
int *iPtr3 = 1;
//error: invalid conversion from `void*' to `int*'
int *iPtr4 = ((void* )0);
return 0;
}
好了,前两种初始化定义是正确的,第一个错误表明0是一个比较特殊的数字,应该是编译器的特殊照顾,但是第二个错误不是符合NULL的第二个宏定义么?但是从指针类型来说却是有问题的,所以咋回事呢?难道编译器对NULL这个关键字做了特殊照顾?
Form 《Understanding and Using C Pointers》
PS:书中也貌似木有解释这个问题。
这个问题其实困扰我很久了,我问很多人"NULL"是什么?有啥用?
大多数人的回答是:"NULL就是系统定义特殊的0,把你初始化的指针指向它,可以防止“野指针”的恶果。"
今天碰到一个C语言的笔试题,还是一道不错的题~~~
Exp 1:
[cpp] view
plain copy
#include <stdio.h>
void fun(int *node)
{
static int N=100;
node=&N;
}
int main()
{
int *node=NULL;
int a=0;
fun(node);
a=*node;
printf("%d\n",a);
return 0;
}
请回答,以上这题的输出结果啥?
从结果中,这题可以区别出对C语言掌握的几个程度。那结果是:100?0?段错误退出?哪一句导致的?为什么?
认为是第一个结果人其实是被static这个关键词欺骗的,但是static是对N的修饰,表示对N的改变不会在fun函数的‘}’之后被释放掉~~~还有一个点就是:C语言的函数永远是值传递(除了数组,呵呵~~~),所以你想改变指针的指向(地址值),就必须传递指针的指针,除非你用return~~~
认为是第二个结果的人掌握了第一个结果的点,并且知道在C语言里是那样定义NULL的:
[cpp] view
plain copy
#undef NULL
#if defined(__cplusplus)
#define NULL 0
#else
#define NULL ((void *)0)
#endif
但是gcc下发现却是段错误退出了~~~
问题在这句:
[cpp] view
plain copy
a=*node;
[cpp] view
plain copy
/*对node进行*运算,node此时木有改变的,还是(void *)0指针~~~所以段错误就出来,当然你可以读取NULL本身的值,即0,但是读取它指向的值,那是非法的,会引发段错误(貌似这种指针的错误还有:操作系统限制用户访问的地址空间,内存木有分到的地址空间(几百KB的嵌入式系统中普遍存在),再加这种就有三种,当然野指针也可能乱指到一般用户合法的地址,然后就乱改,然后就失控了~~~)*/
NULL是个好东西,给一出生的指针一个安分的家~~~
ps:我一开始就以为是0,功力不深啊~~~修炼,修炼~~~
Exp 2:
[cpp] view
plain copy
#include <stdio.h>
int main(...)
{
int *iPtr1 = NULL;
int *iPtr2 = 0;
//error: invalid conversion from `int' to `int*'
int *iPtr3 = 1;
//error: invalid conversion from `void*' to `int*'
int *iPtr4 = ((void* )0);
return 0;
}
好了,前两种初始化定义是正确的,第一个错误表明0是一个比较特殊的数字,应该是编译器的特殊照顾,但是第二个错误不是符合NULL的第二个宏定义么?但是从指针类型来说却是有问题的,所以咋回事呢?难道编译器对NULL这个关键字做了特殊照顾?
Form 《Understanding and Using C Pointers》
PS:书中也貌似木有解释这个问题。
相关文章推荐
- 如何组织构建多文件 C 语言程序(二)
- 如何写好 C main 函数
- Lua和C语言的交互详解
- 关于C语言中参数的传值问题
- 简要对比C语言中三个用于退出进程的函数
- 深入C++中API的问题详解
- 基于C语言string函数的详解
- C语言中fchdir()函数和rewinddir()函数的使用详解
- C语言内存对齐实例详解
- C语言编程中统计输入的行数以及单词个数的方法
- C语言自动生成enum值和名字映射代码
- C语言练习题:自由落体的小球简单实例
- 使用C语言判断英文字符大小写的方法
- c语言实现的带通配符匹配算法
- C语言实现顺序表基本操作汇总
- C语言中进制知识汇总
- C语言判断一个数是否是2的幂次方或4的幂次方
- C语言中计算正弦的相关函数总结
- 使用C语言详解霍夫曼树数据结构
- C语言实现选择排序、冒泡排序和快速排序的代码示例