0%

c 语言 | NULL 解析

最近写了一个尾插法,结果进入了 NULL 的圈套,在这里记录一下。

空指针 NULL

注意区分大小写,null 没有任何特殊含义,只是一个普通的标识符。

1
2
3
4
5
6
7
#include<stdo.h>
int main()
{
int *p=NULL;
printf("%p",p);

}

单步调试可以看出执行int *p=NULL, p 的值为 0x00000000 ,可以看出,NULL在实际底层调用中就是0。

如果一个指针被赋予NULL,应该就相当于这个指针执行了0x0000这个逻辑地址,但是C语言中0x0000这个逻辑地址用户是不能使用的(有些人说是因为0x0000没有映射到物理地址,也有人说是因为0x0000映射到的地址是操作系统用于判断野指针的,我也不太懂,总之就是用户不能使用啦),所以当你试图取一个指向了NULL的指针的内容时,就会提示段错误。

在C语言中,NULL和0的值都是一样的,但是为了目的和用途及容易识别的原因,NULL用于指针和对象,0用于数值。

对于字符串的结尾,使用’\0’,它的值也是0,但是让人一看就知道这是字符串的结尾,不是指针,也不是普通的数值

我们知道,变量一旦定义就要分配内存,指针变量也是如此。例如:

int *p;  //它不是空指针

它的值是随机的,是垃圾值,如果不小心使用了它,运行时一般会引起段错误,导致程序退出,甚至会不知不觉地修改数据。

p 经过定义,就一定在内存中分配了4个字节(32位环境)的空间,只是它的值是随机的,不像int会被初始化为 0,但是它确实指向了一段正常使用的内存。使用 p 时,操作的就是这段内存的数据,幸运的话能够正常运行,不过大部分情况下这段内存是无权操作的。

在不同的系统中,

NULL并非总是和0等同,NULL仅仅代表空值,也就是指向一个不被使用的地址,在大多数系统中,都将0作为不被使用的地址,所以就有了类似这样的定义

#define NULL 0

但并非总是如此,也有些系统不将0地址作为NULL,而是用其他的地址,所以说,千万别将NULL和0等价起来,特别是在一些跨平台的代码中,这更是将给你带来灾难。

下面的写法也是不专业的:

int *p = 0;

而应该坚持写为:

int *p = NULL;

注意 NULL 和 NUL 的区别:NULL表示空指针,是一个宏定义,可以在代码中直接使用。而 NUL 表示字符 ‘\0’,也就是字符串结束标志,它是ASCII码表中的第 0 个字符。NUL 没有在C语言中定义,仅仅是对 ‘\0’ 的称呼,不能在代码中直接使用。

例子

小 demo 1

1
2
3
4
5
int *node=NULL;
int a=0;
a=*node;

printf("%d\n",a);

由于node执行的是NULL,也就是逻辑地址0x0000,而这个地址用于是不能访问的,所以编译器提示段错误。

小 demo 2

1
2
3
4
5
6
7
8
9
#include <stdio.h>

int main(void) {
int i = 1;
int *p= &i;
int *a = p;
*a = 1;
printf("%d",*p);
}

上面这个是正常的。

1
2
3
4
5
6
7
8
#include <stdio.h>

int main(void) {
int *p= NULL;
int *a = p;
*a = 1;
printf("%d",*p);
}

这个是错误的,主要体现在

*a = 1;

a 的地址是 NULL ,这个地址不能使用,所以,也不能赋值。

面试题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#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;

}

运行结果依然是段错误。因为函数是值传递,node指针变量的值并没有被改变,所以这个程序的效果和上一个程序的效果是一样的。

如果要让结果为100,应该怎样写代码呢? 答案是 传递node指针变量的指针给fun,也就是传递一个二级指针,当然相应的fun函数也应该做出改变,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#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;

}
请我喝杯咖啡吧~