C语言学习之空指针NULL以及void指针详解

本文和大家分享的主要是c 语言 空指针NULL 以及 void 指针相关内容,一起来看看吧,希望对大家 学习c语言有所帮助。

空指针 NULL

一个指针变量可以指向计算机中的任何一块内存,不管该内存有没有被分配,也不管该内存有没有使用权限,只要把地址给它,它就可以指向,C 语言没有一种机制来保证指向的内存的正确性,程序员必须自己提高警惕。

很多初学者会在无意间对没有初始化的指针进行操作,这是非常危险的,请看下面的例子:

1. #include

2. int main () {

3. char * str ;

4. gets ( str );

5. printf ( "%s \n " , str );

6. return 0 ;

7. }

这段程序没有语法错误,能够通过编译和链接,但当用户输入完字符串并按下回车键时就会发生错误,在 Linux  下表现为段错误( Segment Fault ),在  Windows  下程序直接崩溃。如果你足够幸运,或者输入的字符串少,也可能不报错,这都是未知的。

前面我们讲过,未初始化的局部变量的值是不确定的,C 语言并没有对此作出规定,不同的编译器有不同的实现,我曾警告大家不要直接使用未初始化的局部变量。上面的代码中, str  就是一个未初始化的局部变量,它的值是不确定的,究竟指向哪块内存也是未知的,大多数情况下这块内存没有被分配或者没有读写权限,使用  gets()  函数向它里面写入数据显然是错误的。

我强烈建议对没有初始化的指针赋值为 NULL ,例如:

char *str = NULL;

NULL  是 “ 零值、等于零 ” 的意思,在 C 语言中表示空指针。从表面上理解,空指针是不指向任何数据的指针,是无效指针,程序使用它不会产生效果。

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

很多库函数都对传入的指针做了判断,如果是空指针就不做任何操作,或者给出提示信息。更改上面的代码,给 str  赋值  NULL ,看看会有什么效果:

1. #include

2. int main () {

3. char * str = NULL ;

4. gets ( str );

5. printf ( "%s \n " , str );

6. return 0 ;

7. }

运行程序后发现,还未等用户输入任何字符,printf()  就直接输出了  (null)  。我们有理由据此推断,gets()  和  printf()  都对空指针做了特殊处理:

· gets()  不会让用户输入字符串,也不会向指针指向的内存中写入数据;

· printf()  不会读取指针指向的内容,只是简单地给出提示,让程序员意识到使用了一个空指针。

我们在自己定义的函数中也可以进行类似的判断,例如:

1. void func ( char * p ) {

2. if ( p == NULL ) {

3. printf ( "(null) \n " );

4. } else {

5. printf ( "%s \n " , p );

6. }

7. }

这样能够从很大程度上增加程序的健壮性,防止对空指针进行无意义的操作。

其实,NULL  是在  stdio.h

中定义的一个宏,它的具体内容为:

#define NULL ((void *)0)

(void *)0  表示把数值 0  强制转换为  void *  类型,最外层的  ( )  把宏定义的内容括起来,防止发生歧义。从整体上来看,NULL 指向了地址为  0  的内存,而不是前面说的不指向任何数据。

在进程的虚拟地址空间中,最低地址处有一段内存区域被称为保留区,这个区域不存储有效数据,也不能被用户程序访问,将NULL  指向这块区域很容易检测到违规指针。

关于虚拟地址空间的概念以及程序的内存分布,我们将在《  C语言和内存  》专题中深入讲解,现在读者只需要记住,在大多数操作系统中,极小的地址通常不保存数据,也不允许程序访问,NULL  可以指向这段地址区间中的任何一个地址。

注意,C 语言没有规定  NULL  的指向,只是大部分标准库约定成俗地将  NULL  指向  0 ,所以不要将 NULL  和  0  等同起来,例如下面的写法是不专业的:

int *p = 0;

而应该坚持写为:

int *p = NULL;

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

void 指针

对于空指针 NULL  的宏定义内容,上面只是对  ((void *)0)  作了粗略的介绍,这里重点说一下 void *  的含义。void  用在函数定义中可以表示函数没有返回值或者没有形式参数,用在这里表示指针指向的数据的类型是未知的。

也就是说,  void *  表示一个有效指针,它确实指向实实在在的数据,只是数据的类型尚未确定,在后续使用过程中一般要进行强制类型转换。

C 语言动态内存分配函数  malloc()  的返回值就是  void *

类型,在使用时要进行强制类型转换,请看下面的例子:

纯文本复制

1. #include

2. int main () {

3. // 分配可以保存 30 个字符的内存,并把返回的指针转换为  char *

4. char * str = ( char *) malloc ( sizeof ( char ) * 30 );

5. gets ( str );

6. printf ( "%s \n " , str );

7. return 0 ;

8. }

运行结果:

c.biancheng.net

c.biancheng.net

这里重点是让大家理解  void * ,它不是空指针的意思,而是实实在在的指针,只是指针指向的内存中不知道保存的是什么类型的数据。

来源:csdn

时间: 2024-12-23 07:16:00

C语言学习之空指针NULL以及void指针详解的相关文章

C语言空指针NULL以及void指针

空指针NULL 在C语言中,如果一个指针不指向任何数据,我们就称之为空指针,用NULL表示.例如: int *p = NULL; 注意区分大小写,null 没有任何特殊含义,只是一个普通的标识符. NULL 是一个宏定义,在stdio.h被定义为: #define NULL ((void *)0) (void *)0表示把数值 0 强制转换为void *类型,最外层的( )把宏定义的内容括起来,我们自己进行宏定义时也推荐这么做,防止发生歧义. 总之,p 的值为 0.你可以输出 p 的值: #in

不要伤害指针(5)--void和void指针详解

原文转载地址:http://blog.csdn.net/sunchaoenter/article/details/6587426 增加自己的想法,作为笔记. 1.概述 许多初学者对C/C++语言中的void及void指针类型不甚理解,因此在使用上出现了一些错误.本文将对void关键字的深刻含义进行解说,并详述void及void指针类型的使用方法与技巧. 2.void的含义 void的字面意思是“无类型”,void *则为“无类型指针”,void *可以指向任何类型的数据. void几乎只有“注释

彻底搞定C语言指针详解

1.语言中变量的实质 要理解C指针,我认为一定要理解C中“变量”的存储实质, 所以我就从“变量”这个东西开始讲起吧! 先来理解理解内存空间吧!请看下图: 内存地址→ 6 7 8 9 10 11 12 13 ----------------------------------------------------------------- ... | | | | | | | |.. ------------------------------- ---------------------------

(转载)C语言单链表实现19个功能完全详解

最近在复习数据结构,想把数据结构里面涉及的都自己实现一下,完全是用C语言实现的. 自己编写的不是很好,大家可以参考,有错误希望帮忙指正,现在正处于编写阶段,一共将要实现19个功能.到目前我只写了一半,先传上来,大家有兴趣的可以帮忙指正,谢谢 在vs2010上面编译运行无错误. 每天都会把我写的新代码添加到这个里面.直到此链表完成. #include "stdafx.h" #include "stdio.h" #include <stdlib.h> #in

&quot;MindManager&quot;学习iOS系列之&quot;CAAnimation-核心动画&quot;详解,让你的应用“动”起来。

"MindManager"学习iOS系列之"CAAnimation-核心动画"详解,思维导图内展示了CAAnimation-核心动画的大多数基本功能和知识,每个part都有代码讲解,展示出CAAnimation-核心动画的清晰轮廓,编者提供了"JPG"."SWF"."PDF"."Word"."Mmap"格式的源文件供给使用.注意:JPG格式仅为图片总览,SWF格式使用

算法学习笔记 KMP算法之 next 数组详解

最近回顾了下字符串匹配 KMP 算法,相对于朴素匹配算法,KMP算法核心改进就在于:待匹配串指针 i 不发生回溯,模式串指针 j 跳转到 next[j],即变为了 j = next[j]. 由此时间复杂度由朴素匹配的 O(m*n) 降到了 O(m+n), 其中模式串长度 m, 待匹配文本串长 n. 其中,比较难理解的地方就是 next 数组的求法.next 数组的含义:代表当前字符之前的字符串中,有多大长度的相同前缀后缀,也可看作有限状态自动机的状态,而且从自动机的角度反而更容易推导一些. "前

Python学习教程(Python学习路线):Pandas库基础分析-详解时间序列的处理

Python学习教程(Python学习路线):Pandas库基础分析-详解时间序列的处理 在使用Python进行数据分析时,经常会遇到时间日期格式处理和转换,特别是分析和挖掘与时间相关的数据,比如量化交易就是从历史数据中寻找股价的变化规律.Python中自带的处理时间的模块有datetime,NumPy库也提供了相应的方法,Pandas作为Python环境下的数据分析库,更是提供了强大的日期数据处理的功能,是处理时间序列的利器. 1.生成日期序列 主要提供pd.data_range()和pd.p

关于空指针NULL、野指针、通用指针

http://www.cnblogs.com/losesea/archive/2012/11/16/2772590.html 首先说一下什么是指针,只要明白了指针的含义,你就明白null的含义了.假设 有语句 int a=10;那么编译器就在内存中开辟1个整型单元存放变量a,我们假设这个整型单元在内存中的地址是 0x1000:那么内存0x1000单元中存放了数据10,每次我们访问a的时候,实际上都是访问的0x1000单元中的10.现在定义:int *p:                 p=&a

c语言指针详解

指针是C语言中广泛使用的一种数据类型. 运用指针编程是C语言最主要的风格之一.利用指针变量可以表示各种数据结构: 能很方便地使用数组和字符串: 并能象汇编语言一样处理内存地址,从而编出精练而高效的程序.指针极大地丰富了C语言的功能. 学习指针是学习C语言中最重要的一环, 能否正确理解和使用指针是我们是否掌握C语言的一个标志.同时, 指针也是C语言中最为困难的一部分,在学习中除了要正确理解基本概念,还必须要多编程,上机调试.只要作到这些,指针也是不难掌握的. 指针的基本概念 在计算机中,所有的数据