指针与引用(四)
前言
前面介绍了指针的数据类型和指针的运算,下面对指针的数据类型和指针运算做一个小结。
1. 有关指针的数据类型的小结
变量定义 | 类型表示 | 含义 |
int i; | int | 定义整型变量 i |
int * p; | int * | 定义 p 为指向整型数据的指针变量 |
int a[5]; | int [5] | 定义整型数组 a ,它有 5 个元素 |
int * p[4]; | int * [4] | 定义指针数组 p ,它由 4 个指向整型数据的指针元素组成 |
int (* p)[4]; | int (*) [4] | p 为指向包含 4 个元素的一维数组的指针变量 |
int f( ); | int ( ) | f 为返回整型函数值的函数 |
int * p( ); | int * ( ) | p 为返回一个指针的函数,该指针指向整型数据 |
int ( * p)( ); | int ( * ) ( ) | p 为指向函数的指针,该函数返回一个整型值 |
int ** p; | int ** | p 是一个指针变量,它指向一个指向整型数据的指针变量 |
int * const p; | int * const | p 是常指针,其值是固定的,即其指向不能改变 |
const int * p; | const int * | p 是指向常量的指针变量,不能通过 p 改变其指向对象的值 |
const int * const p; | const int * const | p 是指向常量的常指针,其指向不能改变,且不能通过 p 改变其指向的变量的值 |
void * p; | void * | p 是一个指针变量,基类型是 void (空类型),不指向具体的对象 |
2. 指针运算小结
2.1 指针变量加/减一个整数
一个指针变量加/减一个整数是将该指针变量的原值(一个地址)和它指向的变量所占用的内存单元字节数相加或相减。如 p + i 代表 p + i * d,d 为 p 所指向的变量单元所占用的字节数。这样就可以保证 p + i 指向 p 下面的第 i 个元素。常见的运算:
p ++, p --, p + i, p - i, p += i, p -= i
2.2 指针变量赋值
将一个变量地址赋给一个指针变量。
p = &a; //将变量 a 的地址赋给 p
p = array; //将数组 array 首元素的地址赋给 p
p = array[i]; //将数组 array 第 i 个元素的地址赋给 p
p = max; // max 为已定义的函数,将 max 的入口地址赋给 p
p1 = p2; // p1 和 p2 都是同类型的指针变量,将 p2 的值赋给 p1
2.3 指针变量可以有空值,即该指针变量不指向任何变量
p = NULL; 使 p 指向地址为0的单元,即指针不指向任何有效的单元。p 的值等于 NULL 和 p 未被赋值是两个不同的概念。前者是有值的(值为0),不指向任何变量,后者虽未对 p 赋值但并不等于 p 无值,只是它的值是一个无法预料的值,也就是 p 可能指向某一个未指定的单元。这种情况是很危险的。因此在引用指针变量之前应对它赋值。
2.4 两个指针变量可以相减和比较
如果两个指针变量指向同一个数组的元素,则两个指针变量值之差是两个指针之间的元素的个数。指向前面的元素的指针变量小于指向后面元素的指针变量。
2.5 对指针变量的赋值应该注意类型问题
如果一定要对不同类型的指针变量赋值,可以用强制类型转换。例如:
int * p1;
char * p2;
float * p3;
p1 = p2; p2 = p3; p3 = p1; //下面的赋值不合法
//不同类型的指针变量赋值,要强制类型转换
p1 = (int *)p2;
p2 = (char *)p3;
p3 = (float *)p1;