一、指针基础
在计算机内部存储器中,每一个字节单元,都有一个编号,称为地址。
内存单元的地址称为指针。
指针是一种构造数据类型。
所有类型的指针(int 、char......)在32位计算机上都是32位(4个字节)。
二、指针变量
(1)指针变量的定义
概念:
专门用来存放地址的变量,称为指针变量。
定义:
数据类型 *变量名;
例如:
int *p;
p是一个指针变量,它的值是某个整型变量的地址,或者说,p指向某个整型变量。
注意:
***指针变量的变量名是“*”后面的内容,而不是“*p”,“*”只是说明定义的变量是
一个指针变量。
***一个指针变量只能指向同类型的变量。
***虽然所有类型的指针变量都是等长的,但是仍然需要定义指针变量的数据类型,
因为对指针变量的其他操作(加、减等)都需要涉及指针所指向的变量的数据宽度。
(2)指针变量的初始化
未经初始化的指针变量不能随便使用,否则将会造成程序运行错误。
指针变量的值只能是变量的地址或是NULL,不能是其他数据,否则将会引起错误。
使用取地址符“&”来获取变量的地址:
&变量名
例如:&a ===》变量a的地址
例如:
int *p,i;
p = &i;
(3)指针变量的引用
&a ===》取变量a的地址
*a ===》取指针变量a所指向的内存单元中的内容
变量的访问:
***直接访问
int a = 10;
通过变量名a可以直接访问变量的值。
***间接访问
int a = 10;
int *p = &a;
通过一个指针变量p去访问它所指向的对象a的值(*p操作)。
p = &a ===》*p和a指向同一块内存单元
注意:
int *a;
*a = 10;
已经定义了指针变量a,但是没有对它进行初始化,即没有让它指向一个对象。那么a的值
是不确定的,即随机指向一个内存单元,这样的指针称为野指针。在执行代码“*a = 10;”
时通常会出现“segmentation fault(段错误)”的错误,原因是访问了一个非法地址。
因此,在对指针变量进行引用时,一定要确保它已经指向一个合法的对象。
(4)指针变量的运算
指针变量的运算是指指针变量所存放的值(地址值)作为运算符而进行的运算。因此,指针运算的实质是
地址的运算。
***指针的算数运算
+ p+n 指针向地址大的方向移动n个数据
- p-n 指针向地址小的方向移动n个数据
++ p++或++p 指针向地址大的方向移动1个数据
-- p--或--p 指针向地址小的方向移动1个数据
- p-q 两个指针之间相隔数据元素的个数
p+n表示的实际内存单元的地址量是:p+sizeof(p的数据类型)*n
p-n表示的实际内存单元的地址量是:p-sizeof(p的数据类型)*n
例如:
sizeof(int) 是4,sizeof(int)是8
int型指针p+2,地址增加了8,相当于两个整数;
double型指针p+2,地址增加了16,相当于两个双精度浮点数。
两指针相减时,注意必须是同种数据类型的的指针,结果为两指针之间相隔数据元素的个数,实际是按如下的
公式进行计算的:
(p-q)/类型字节数
***指针变量的关系运算
两指针之间的关系运算,实际上是他们所存放的地址之间的关系运算。指向地址大的指针大于指向地址小的指针。
关系运算分类:
>、< 、>=、 <=、 ==、 !=
注意:
具有不同数据类型的两指针之间的关系运算没有意义;指向不同数据区域的两指针之间的关系运算没有意义。
指针与一般整数变量之间的关系运算没有意义,但可以和0值进行等于或不等于的关系运算,用来判断
指针是否为空。
(5)空指针
C语言标准中定义了一个NULL指针,它可以用来说明一个指针目前并未指向任何对象。
对NULL指针进行引用操作是非法的,因为它还没有指向任何对象。因此,在对指针进行引用时,应该先判断该指针
是否为NULL,这样才不会出现错误。
int *p = NULL; //引用时,在编译阶段就出现错误
int *p; //野指针,引用时,编译不出错,在执行时出现段错误