一:空指针与空类型指针
空指针:我们在学习某些函数时,可能会返回空指针。
例如:fopen函数在打开文件时,如果打开文件失败,那么就会返回空指针,如果打开文件成功,就返回该文件的文件指针。
空类型指针:还有一些函数在传参时,实参类型为void*
例如:qsort函数不挑数据类型,就可以对数据进行排序,就是因为它的实参设置的是void类型的指针
二者的区别:
空指针:
可以是任意类型的指针,只是该指针变量中存储的数据(或者说存储的地址)是NULL。空指针是不能被解引用的,因为NULL地址指向的那块空间,没有分配给操作者使用,一但对NULL地址进行解引用,程序就会报错。
空类型指针:
首先,空类型与其他类型相同,都是属于基本类型,但是在对空类型的指针来说,他比其他类型的指针有一个很大的优点,可以接收任意类型变量的地址。
可以看到,这段代码在进行编译后,报出了一个警告:“初始化”: 从“int *”到“char *”的类型不兼容 。就是因为我们在编写第8行代码时,将int类型的变量的地址直接赋值给了一个char类型的指针,所以编译报出了警告。但是却没有对第9行的代码进行警告。就是因为空类型指针可以接收任意类型变量的地址。
但是空类型指针也有一个最大的缺点那就是它也不能进行解引用操作。
可以看到,我们如果直接对这个空类型的指针进行解引用操作,编译器会直接报错。因为指针的类型不仅代表了这个指针变量指向的数据的类型,也代表了如果对这个指针进行解引用的话,可以访问几个字节的空间。 int类型指针在进行解引用操作时,会从这个地址指向的字节开始,还会向后再访问三个字节的空间。char类型的指针变量在进行解引用操作时,只会访问这个地址所指向的那一个字节。
而空类型(void类型)没有指定的大小,操作系统不知道对其进行解引用后,到底访问几个字节的空间。
总结空指针与空类型指针:
空指针是因为该指针变量存放的数据是NULL(空)。空类型指针是指该种指针的类型为空。
二者都不能进行解引用。
二:#define与typedef
#define char_ptr char*
typedef char* char_pc;char_ptr a, b;
char_pc c, d;现在问变量a,b,c,d哪些不是指针 ( 操作在32位地址线的平台进行的,该种类型平台指针变量大小都为4个字节大小)
可以看到,只有b求出的结果是1(也就是正常char类型变量的大小),其他三个变量字节大小 都为4。所以 a ,c ,d 都是指针,只有b不是指针。
那这是什么原因呢??????
我们知道#define是一种宏的替换,在程序进行预编译的阶段,所有被#define定义的都会进行替换。
那么上面的代码就可以写成这个样子
替换后,代表着定义指针的 * 与变量a进行结合了,所以,a是一个指针,而b是一个char类型的变量
而typedef是将某种类型进行重命名,那么重命名后的char_pc代表的就是字符型的指针类型。就像size_t一样
所以定义后的结果里 c , d ,都是指针变量。
三:#include<stdio.h>和#include"stdio.h"
#include<stdio.h>:这种引头文件的方式,程序会直接去封装好的头文件库里查找该头文件。
#include"stdio.h" :这种引头文件方式,程序会先在主函数所在文件夹里查找该头文件。如果没有找到,那么它会自动的去库里面查找。