前言
首先说明,本文不适合新手,如果你刚刚接触指针,可以看看前五点,这是我认为指针中比较重要的细节,例题部分酌情尝试。
如果你自认为指针学的不错,胸有成竹,请尝试最后的例题,如果在不借助编译器的情况下正确率能达到百分之80,那么恭喜你,你已经是指针高手啦!!!
一.指针的概念
指针就是地址,是内存中每个字节空间的编号。
指针变量,是保存指针的变量。
口语表述所谈的指针,其实是指针变量。之所以会将两者混谈是因为,当指针变量做右值使用时,指针和指针变量的意义相近(指针变量的空间——左值;指针变量的内容——右值)。说明:下文我所谈的指针,通常是说指针变量,当我想说真正意义上的指针时,会用“地址”来表述
二.指针类型
指针很多类,int*, double*, char*,还有数组指针,函数指针等。不同类型的作用在于,解引用访问的字节个数以及看待这块内存的方式不同,++,--跳过的字节数也不同
例如对char* 解引用,访问1个字节,对int*解引用,访问4个字节;对int* 解引用,看待这4个字节,最高为符号位,其余是数值位,对float解引用,这4个字节高位是阶码,低位是尾数。
三.空指针
C语言中,NULL是一个宏值,定义为:#define NULL ((void *)0),而void* 可以赋给任意类型的指针
C++在NULL的定义上给自己挖了一个坑:#define NULL 0,这样会导致函数重载或者模版的类型推导时,将指针和整形类型混淆。所以C++11引入了一个nullptr的关键字,它是一个空指针常量,类型是nullptr_t(类似一个枚举类型)。
对空指针解引用会引发异常,这不是编译过程的问题,而是运行过程触发中断,操作系统向进程发送信号(集成在CPU上的MMU再进行页表转化时,访问0号地址的代码区,MMU转化失败,硬件异常)
四.数组的概念
数组是具有相同类型的变量的集合
指针和数组在使用上非常类似,但它们是两个完全不同的概念
五.关于数组的若干概念辨析
1.&arr[0] VS &arr
前者是数组arr的首元素的地址,即数组首元素最低字节的地址;后者是数组的地址,即数组的最低字节的地址。
二者在数值上是相等的,但是解引用访问的空间不同,++,--的步长也不同。前者解引用访问首元素,++是加上首元素的字节数,后者解引用访问整个数组,++是加上整个数组的字节数。
2.字符串存储的两种方案
char arr[] = "hello world"
const char* p = "hello world"
前者是在栈区开辟一个数组,存储的是“hello world\0”,后者是在只读数据区开辟空间,存储“hello world\0”。
3.数组传参
数组传参会降为成指针,降维成指向其内部元素类型的指针。编译器这样处理是为了减少拷贝,提高效率。
六.例题
注意:以下结果均在32位平台验证,即指针大小为4个字节
1.sizeof和strlen结果
2.
3.
4.
5.
6.
7.
一定要画图!!!