void 、 void* 和 NULL的理解

前言

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

需使用初始化的局部变量

先看一段代码

#include
#include
#pragma warning(disable:4996)
int main()
{
	char *arr;
	gets(arr);
	printf("%s\n", arr);
	system("pause");
	return 0;
}

这段程序本没有语法错误,但在vs2013会报错,即arr未初始化,但在有的编译器当中当输入字符串之后,按回车程序直接崩溃,而在Linux表现这段错误(Segment Fault),这是为什么?

未初始化的局部变量的值是不确定的,C语言没有做规定,不同编译器可能有不同结果(所以不要使用没初始化的局部变量),在上例子中arr就是未初始化的局部变量(指针变量也是变量),他的值是未知的,指向哪块内存也不知道,大多数情况这块内存没有被分配,或者没有读写权限。

所以,没有初始化的指针变量初始化为NULL

char *arr = NULL;
NULL

NULL是“零值”的意思,表示空指针,从表面上理解空指针是不指向任何数据的指针,是无效指针,程序使用不会产生任何效果。(注意区分大小写,null没任何含义)

在上例子中会出现什么效果呢!

#include
#include
#pragma warning(disable:4996)
int main()
{
	char *arr = NULL;
	gets(arr);
	printf("%s\n", arr);
	system("pause");
	return 0;
}
void 、 void* 和 NULL的理解_第1张图片
运行之后发现还有错,(1)gets()不会让用户输入字符串,也不会向指针指向的内存写入数据;(2)printf()不会读取指针指向的内容,只是给出提示,让用户意识到使用了一个空指针;

实际上很多库函数都会对空指针进行判空:(防止对空指针进行无意义的操作)

(1)
if(psrc == NULL)
     return 0;
else
     {;}
(2)
//断言,头文件#include
assert(psrc);//或者
assert(psrc!=NULL);
//如果为空,他会报错到具体哪一行

请看下图:

void 、 void* 和 NULL的理解_第2张图片

看到其实NULL是一个宏,(void *)0表示把0强制转化为void*类型,最外层()防止发生优先级等问题。所以,NULL指向了地址为0的内存,不是不指向任何输入。

在大多数操作系统中,极小的地址通常不保存数据,也不允许程序访问,NULL可以指向这段地址区间的任何一个地址。

注:(1)C语言并没有规定NULL的指向,只是大部分标准库规定将NULL指向0;

       (2)NULL和NUL的区别,NULL表示一个宏定义,空指针,可在代码中使用,NUL表示字符串结束标志'\0',NUL没有在C语言中定义,所以不可以在代码中使用。

void*

void不可以定义变量,因为定义变量前提是要开辟空间,而void是空类型。void*可以定义变量,指针在32位平台占4个byte,但是void*定义的变量不可以解引用。

void用在函数定义当中可以表示函数没有返回值,或者没有形式参数,,而void*表示指针指向的数据的类型是未知的。void*表示一个有效的指针,他确实指向一个实实在在的数据,可是数据的类型尚未确定,在后续的使用过程一般要强制类型转化。

例:

动态内存分配函数malloc(),原型定义如下:

void *malloc( size_t size );

malloc()的返回值为void*类型,所以在使用的时候要强制类型转化为需要的类型,请看下例

#include
#include
#pragma warning(disable:4996)
int main()
{
	char *arr = (char *)malloc(sizeof(char)*20);//开辟可以保存20个字符的内存大小,返回值转化为char*
	gets(arr);
	printf("%s\n", arr);
	system("pause");
	return 0;
}

你可能感兴趣的:(c语言概念)