二、指针的定义
每个指针都有一个与之关联的数据类型,该数据类型指定了指针所指向的对象的类型。例如,一个int型指针只能指向一个int型对象。
在C++中,使用*符号把一个标识符声明为指针
以下给出一些指针定义的例子:
int *i; // int型指针,i用于指向int型对象
double *d; // double型指针,d用于指向double型对象
string *s; // string型指针,s用于指向string型对象
vector<int> *v; // vector<int>型指针,v用于指向vector<int>型对象
注意,*符号除了可以放在标识符前,也可以放在数据类型后,如下指针定义风格也是合法的:
int* i; // int型指针,i用于指向int型对象
double* d; // double型指针,d用于指向double型对象
string* s; // string型指针,s用于指向string型对象
vector<int>* v; // vector<int>型指针,v用于指向vector<int>型对象
但是这种指针定义风格容易引起一种误解: 把 int*, double*, string*, vector<int>*当成了一种数据类型。如对于以下声明:
int* i1, i2;
很容易会被误解成: i1 和 i2 均为指向int型数据的指针。
但实际上,只有 i1 是指向int型数据的指针,而 i2 则是一个int型数据。
假如要在同一声明语句里声明两个统一数据类型的指针,可以是如以下例子:
int *i1, *i2;
也可以如此声明:
int* i1, *i2;
又或者是分开两句声明那就更不会容易引起混淆:
int *i1;
int *i2;
为了更好理解指针对象,建议声明指针变量时,将*符号紧贴在指针变量名的前面放置。
三、指针的初始化
int val = 1024;
int *p1, *p2, *p3, *p4;
p1 = &val;
p2 = p1;
p3 = 0;
p4 = NULL;
注意,避免使用未初始化的指针。在程序编译时,未初始化的指针错误往往不会被找出来,可往往到运行时,程序则是因为指针未初始化而崩溃。
对于初始化为0值的指针,编译器可以检测出来,程序可判断该指针并未指向一个对象。
所以建议在声明一个指针时,假如没有初始值,那最起码应该将该指针初始化为0值,避免错误。
最后,总结如下,声明指针时应该初始化指针,对指针进行初始化或赋值,只能是使用以下4种类型的值:
1. 0值常量表达式,例如,在编译时可获得0值的整型const对象或字面值常量0.
对于上面第一种类型,简单举例说明一下,以下的声明是合法的:
const int val = 0;
int *p1, *p2, *p3;
p1 = val;
p2 = 0;
p3 = NULL;
但,以下声明是不合法的:
int cval = 0;
int *p = cval;
因为在上面一个例子中, val 是一个const整型常量,值为0,所以赋值给指针 p1 合法。但对于下面一个例子, cval并不是一个常量,它是一个整型变量,所以不能赋值给指针 p。
另外,再次提醒,由于指针的类型用于确定指针所指向对象的类型,因此初始化或赋值时必须保持类型匹配。指针用于间接访问对象,并基于指针的类型提供可执行的操作,例如,int 型指针只能把其指向的对象当作 int 型数据来处理,如果该指针确实指向了其他类型(如 double 类型)的对象, 则在指针上执行的任何操作都有可能出错。
给出以下一个例子:
#include <iostream>
using namespace std;
int main(){
int i1 = 9;
double d1;
double *p1;
p1 = (double*)(&i1);
d1 = *p1;
cout << d1 << endl;
return 0;
}
输出结果如下: