1. 指针变量的定义
(1)变量的分类:变量分为普通变量和指针变量,其中,内容变量(普通变量)存放的是内容值;地址变量(指针变量)存放的是地址值。
(2)指针变量的定义格式:类型名 *指针变量名; 例如:指针变量 int *p,*q; , 内容变量 int a,b;
- 定义变量(普通变量、指针变量)必须在其定义的普通变量名或指针变量名前面有类型名。
- 定义指针变量时,指针变量名前面的 “ * ” 表示现定义的是一个指针类型的变量。“ * ”并不是指针变量名的一部分,只是一个标志,指示该变量为指针类型的变量。
- 指针变量专门用来存放地址,禁止将一个整型值直接赋给一个指针变量。
(3)指针变量的引用
- “ & ” 取地址运算符,通过 “ & ” 运算符可以取出普通变量的地址。
- “ * ” 指针运算符 ,“ * ” 可以取出指针变量所指向的普通变量的值(间接引用普通变量)。
//指针变量的引用
int *p ; //定义一个指针变量 p
int *q ; //定义一个指针变量 q
int a = 117 ; //定义一个普通变量,并初始化
int b ; //定义一个普通变量
*p = a ; //* 指针变量名 = 内容值,此时的 *p 指定的是内容值 117
p = &b ; //此时指针变量 p 指向的是 b 的地址,而非普通变量 b
&b = p ; //该表达式与 p = &b 意思一样
//注意
int a ; //普通变量 a
int *p = &a ; // 指针变量 p 指向普通变量 a 的地址
//等价于:普通变量与指针变量的对应关系采用 “ & ” 符合建立相等连接关系
int a ;
int *p ;
p = &a ; //或者 &a = p ;
- “ * ” 可表示:乘(双目运算符)、指针运算符、指针的标志 。
(4)指针变量引用时的注意事项
- 可以通过赋值使一个指针变量 “指向”某一个普通变量(指针变量 = &普通变量,例如:int a; int *p; p = &a ;)。
- 先让指针变量指向一个确定的存储单元后,再通过该指针变量引用它所指向的存储单元,例如:int *p; int a; *p = a; 。
- 变量名(普通变量、指针变量)都表示其存储单元内的值。p1 = p2; 意思是 p1 指向 p2 所指向的存储单元。
- 若指针变量 p 指向普通变量 a ,即将普通变量 a 的地址赋给指针变量 p ,例如:int *p; int a = 117; p = &a ; 。
- 所有的指针变量在内存中分配的字节数相同,指针变量所指向的是存储单元的地址,地址为整型数据,则占据连个字节,使用 sizeof 关键字可以计算指针变量的字节数。
口诀:地址变量得地址,得谁地址指向谁;有 “ * ”为内容值,“ * ”在左边为写, 其他都是读;无 “ * ”为地址,地址赋值改指向;指针变量不仅要定义,还有初始化,再进行使用。
2. 指针变量的使用
(1)注意:定义指向数组元素的指针变量与指向普通变量的指针变量完全一样。
(2)若数组作为形参,则将数组名作为指针变量来处理,例如:int fun( int a[10] ) 等价于 int fun( int a[] ) 等价于 int fun( int *a )。
(3)指向多维数组的指针变量
注意:只有列指针才是“真正”指向元素,即指向某个元素的存储单元;一维数组名表示列指针,二维数组名表示列指针。
若 a 是二维数组,则有如下几种情况:
- a + i 是行指针,即指向一整行,若对它加 1 则指向下一行。
- *( a + i ) 和 a[ i ] 一样,都是一个列指针,即指向的是一个元素。
- *( a + i ) + j 和 a[ i ] + j 一样,都表示元素 a[ i ][ j ] 的地址,即与 &a[ i ][ j ] 。有 *( a + i ) + j 等价于 a[ i ] + j 等价于 &a[ i ][ j ] 。
- *( *(a+i)+j) 等价于 *(a[ i ] + j ) 等价于 ( *(a+i))[ j ] 等价于 a[ i ][ j ] ,都表示元素 a[ i ][ j ] 。
(4)指向函数的指针变量
注意:函数名与数组名一样,是起始地址,而且是一个地址常量。
- 定义格式:函数类型名 (*指针变量名)();
- 定义指向函数的指针变量时,要注意有两个小括号必须有,不需要定义形参。
- 单独的函数名代表该函数的首地址(函数的入口地址)。
- 函数的指针变量只能指向函数的入口处(函数的首地址),不能指向函数中的某条指令(注意:对指向函数的指针变量加 1 没有任何意义)。
- 给指向函数的指针变量赋值时,只写函数名即可,不必写参数。
//指向函数的指针
int (*add_student)();
(5)返回指针的函数
- 定义格式:类型名 *函数名(形参列表){ },并且利用 return 语句返回地址值。
//返回指针的函数
int *insert(int a,int b)
{
//函数体
return //返回指针变量
}
(6)指针数组
- 若一个数组的所有元素均为指针类型(地址),则称为指针数组(地址数组)。
- 指针数组定义格式:类型名 *数组名[常量表达式]; 例如:int *s[10];
- 指针数组的每个元素都是指针类型(地址),即它的每个元素都相当于一个指针变量。
注意:注意指针数组与定义指向由 m 个元素组成的一维数组的指针变量之间的区别。指针数组:类型名 *数组名[常量表达式]; ,行指针变量:类型名 ( * 指针变量名 )[常量表达式];
int *stu[10] ;//指针数组
int (*p)[10] ;//行指针变量
(7)指向指针的指针变量
- 用来存放指针变量地址的指针变量称为指向指针的指针变量
- 定义格式:类型名 **指针变量名;
//指向指针的指针变量使用情况
int a ;
int *p = &a;
int **q = &p ; //又或者 *q = p
(8)空指针
- 指针变量可以有空值,即指针变量不指向任何变量,不指向任何有用的存储单元。在系统中已将 NULL 定义为 0 ,即 NULL = 0 。
- 当一个指针变量的值为空指针时,不能引用它所指向的存储单元。
- 若某指针(地址)的基本类型为 void 型,则有引用时应进行相应的强制类型置换。
- 指针变量(地址变量)在定义之后还需进行初始化。
//错误示例
int *q = NULL ;
int *p = a ;
int a[] = {1,2} ;
*q = *( p + 1 );
//上述代码出现错误,因为 q 指向了空指针,*q 不能指向 *(p+1)