void*指针
void*指针是一种特殊的指针类型,可以用于存放任意对象的地址。void*指针和其他指针一样,存放着一个地址,但是这个地址的类型是未知的。
指向常量的指针
指针既可以指向常量也可以指向变量。指向常量的指针( pointer to const )并不是说其所指向的对象必须是一个常量(可以是变量,变量本身也是可以被赋值的,同时指针p也可以指向其他地址),而是要求不能通过该指针改变对象的值(可以通过其他途径改变对象的值)。
const int pi = 3;//pi 是一个常量,其值不能更改
int *ptr = π//错误!ptr是一个普通指针,不能指向一个常量
const int *cptr = π//cptr是一个指向常量的指针
*cptr = 42;//错误!不能给cptr赋值
【这里 const int *cptr = π与int const *cptr = π是一样的】
一般地,指针的类型必须与其所指向的对象的类型保持一致。这里是个例外,允许一个指向常量的指针指向一个非常量对象:
int dval = 3;//dval是一个变量
cptr = &dval;//正确
常量指针(const 指针)
把指针本身定义为常量的指针叫常量指针( const pointer )。常量指针在定义时就必须初始化,一旦初始化完成,其值就不能改变了,也就是地址不再发生变化了。
int Num = 0;
int *const curNum = &Num;//curNum是一个常量指针,指向一个int对象
const int Num2 = 1;
const int *const curNum2 = &Num2;//curNum2是一个常量指针,指向一个int型常量对象
常量指针是说指针本身是一个常量,并不意味着不能通过指针修改其所指向的对象的值。能否修改所指对象的值只和该对象的类型有关。若所指对象被const修饰,也就是说是一个常量对象,则不能修改,否则能修改。
const数组
const int a[] = {1,2,3,4};
其实数组变量本身就是const指针,而这里的const的作用是表示数组中的每一个元素都是不可变的,所以数组中的元素只能通过初始化来赋值。
复制指针
混淆指针与指针所指向的数据,常见于字符串使用的情形:
char = *p, *q;
p = " xyz ";
我们可能认为p的值就是“xyz”,但是实际情况并非如此,p的值实际上是一个指向由‘x’,‘y’,‘z’,‘\0’构成的数组第一个元素的指针。
在指向语句q = p后,p和q都成为指向该数组第一个元素的指针。但是需要注意的是,这个赋值语句并没有同时复制内存中的字符。也就是说,复制指针并不同时复制指针所指向的数据。
在执行语句 q[1] = 'Y'; 后,q所指向的内存存储的是“xYz”,p和q指向的是同一个存储空间,那么p所指向的存储空间存储的字符串也是“xYz”。
【ANSI C标准中,禁止对string literal作出修改。K&R C对此说明,试图修改字符串常量的行为是未定义的。某些C编译器还允许q[1] = 'Y';这种修改行为,如LCC v3.6。但是,这种写法不提倡。】
NULL指针
在C语言中,将一个整数转换为一个指针所得到的结果取决于具体编译器的实现。但是对于常量0,编译器保证由0转换而来的指针不等于任何有效的指针。常量0对被NULL替代。
#define NULL 0
注意:常量0被转换为指针使用时,这个指针不可以被解引用。换句话说,当我们将0赋值给一个指针变量时,不可以用该指针指向内存中存储的内容。下面这句是非法的:
if ( strcmp( p, ( char *) 0) == 0)...
因为库函数strcmp的实现中包含查看它的指针参数所指向的内存中的内容的操作。
NULL 指针并不指向任何对象。记住,除非用于赋值或者比较运算,出于其他任何目的使用NULL指针都是非法的。
函数指针
函数指针指向的是函数而非对象。要想声明一个可以指向函数的指针,只需用指针替换函数名:
bool lengthCompare( const string &, const string & );//函数
定义一个函数指针 pf ,pf 指向函数 lengthCompare ,函数的两个参数是 const string 的引用,返回值是 bool 型。
bool (*pf)( const string &, const string & );
注意上式函数指针要小括号包住。如若不加括号,意义截然不同:
bool *pf ( const string &, const string & );
其意义为 pf 是一个返回值为 bool * 的函数(pf 是一个普通函数,只是其返回类型为 bool * )。
指向数组的指针
声明一个指向数组的指针,形似:
int ( *pi )[ 10 ];
( *pi ):pi是一个指针;
( *pi )[ 10 ]:pi是一个指向数组的指针;
int ( *pi )[ 10 ]:pi是一个指向整型数组的指针。
看两组语句是否合法:
//第一组
int vector[ 10 ] ;
int *vp = vector;
//第二组
int matrix[ 3 ][ 10 ];
int *mp = matrix;
一般地,指针的类型要与其所指向的对象的类型保持一致。 vector 和 vp 具有相同的类型,都是指向 int 型的指针,所以没有问题。而 matrix 是一个指向整型数组的指针(matrix是二维数组,它的第一个元素是一个数组),mp 是一个指向整型的指针,所以 mp 的初始化是不合法的。
指针数组
指针数组是一个数组,数组里的元素是指针。例如:
int *api[ 10 ];
api[ 10 ]:api 是一个数组;
*api[ 10 ]:api 是一个数组,数组里的元素是指针;
int *api[ 10 ]:api 是一个数组,数组里的元素类型是指向 int 型的指针。