指针辨析

指针是什么?

任何程序数据载入内存后,在内存都有它们的地址,这就是指针。而为了保存一个数据在内存中的地址,我们就需要指针变量。

因此:指针是程序数据在内存中的地址,而指针变量是用来保存这些地址的变量。

指针数组存放指针的数组)数组指针(指向数组的指针)

指针数组:首先它是一个数组,数组的元素都是指针,数组占多少个字节由数组本身决定。它是“储存指针的数组”的简称。

数组指针:首先它是一个指针,它指向一个数组。在32 位系统下永远是占4 个字节,至于它指向的数组占多少字节,不知道。它是“指向数组的指针”的简称。

int *arr_a [10];            //数组指针
int  (*)arr_b[10];          //指针数组

ptr1先与“[]”结合,构成一个数组的定义,数组名为ptr1,int *修饰的是数组的内容,即数组的每个元素。那现在我们清楚,这是一个数组,其包含10个指向int 类型数据的指针,即指针数组。

至于ptr2就更好理解了,在这里“()”的优先级比“[]”高,“*”号和ptr2 构成一个指针的定义,指针变量名为ptr2,int 修饰的是数组的内容,即数组的每个元素。数组在这里并没有名字,是个匿名数组。那现在我们清楚ptr2 是一个指针,它指向一个包含10个int 类型数据的数组,即数组指针。

二 指针变量

指针变量是用来存储地址的,而一般变量是存储数值的。指针变量可指向任意一种数据类型,但不管它指向的数据占用多少字节,一个指针变量占用四个字节。

定义格式: 类型名 * 指针变量名。二维指针变量 int **p,可以理解为基类型是(int *)类型。

三 指针变量的的引用

&是取地址符,*是间接访问运算符,它们是互逆的两个运算符。在指针变量名前加间接访问运算符就等价于它指向的量。

四 指针的运算

int  *p中*p和p的差别:

*p可以当做变量来用, * 的作用是取后面地址p里面的数值; p是当做地址来用。

*p++和(*p)++之间的区别:

*p++是地址会变;(*p)++是数值会变化。

三名定义:

数组名: 表示第一个元素的地址。数组名不可以自加,它是地址常量名。

函数名:表示函数的入口地址。

字符串常量名:表示第一个字符的地址。

五 空指针和void*类型指针

空指针:指向空,或者说不指向任何东西。在C语言中,我们让指针变量赋值为NULL表示一个空指针,而C语言中,NULL的本质是((void*) 0),在C++中NULL的实质是0。换种说法:任何程序不会存储在地址为0的内存块中,它是被操作系统预留的内存块。

void*类型指针:由于void是空类型,因此void*类型的指针只保存了指针的值,而丢失了类型信息,我们并不知道它指向的数据类型是什么,只指定这个数据在内存中的起始地址,如果想要完整的提取指向的数据,就必须先为它做出正确的类型转换,然后在解引用。因为,编译器不允许直接对void *类型的指针进行解指针操作。

六 指针的赋值

浅拷贝:指针之间的赋值是一种浅拷贝,是在多个编程单元之间的共享内存数据的高效的方法。

深拷贝: 数据真正的被拷贝了,在每个内存中都有自己的一份,对目标数据的操作不受影响。

七 const和指针

如果const后面是一个类型,则跳过最近的原子类型,修饰后面的数据。(原子类型是不可再分割的类型,如int, short, char, 以及typedef包装后的类型)

如果const后面就是一个数据,则直接修饰这个数据。

简单总结:近水楼台先得月,忽略类型名,距离哪个变量近就修饰哪个。

const int *p;             //const修饰*p,p是指针p可变,p指向的对象*p不可变
int const *p;             //const修饰*p,p是指针p可变,p指向的对象*p不可变
int *const p;             //const修饰p,p是指针p不可变,p指向的对象*p可变
const int * const p;      //前一个const修饰*p,后一个const修饰p,指针p和p指向的对象都不可变

猜你喜欢

转载自blog.csdn.net/ox0080/article/details/80188067