【&地址运算符 】
只需对变量应用地址运算符(&),就可获得他的位置;例如,如果 home 是一个变量,则 &home 是他的地址。
如下程序演示了&运算符的用法
int main()
{
int donuts = 6;
cout << "donuts value =" << donuts << endl;
cout << "and donuts address =" << &donuts << endl;
return 0;
}
【*运算符 】
指针用于存储值的地址,与处理存储的策略刚好相反,将地址作为指定的量,将值作为派生的量。
*运算符应用于指针,可以得到该地址处存储的值。例如,假设 manly 是一个指针,则 manly 表示的是一个地址,而 *manly 表示存储在该地址处的值。*manly 与常规int变量等效。 如下程序说明了这几点,还演示了如何声明指针
int main()
{
int updata = 6; //声明一个变量
int* p_updata; //声明一个指针
p_updata = &updata; //为int*类型指针分配地址
//两种方法表示数值
cout << "value: updata =" << updata;
cout << ", *p_updata = "<< *p_updata << endl;
//两种方法表示地址
cout << "addresses:&updata = " << &updata;
cout << ", p_updata = "<< p_updata << endl;
//用指针改变值
*p_updata += 1;
cout << "now updata: "<< updata << endl;
return 0;
}
从中可知,int变量 update 和指针变量 p_updata 只不过是同一枚硬币的两面。
变量update表示值,使用&运算符来获得地址;而指针变量p_updata表示地址,使用*运算符来获得值。因此*p_updata 和 update 完全等价。可以像使用int变量那样使用*p_updata。
【声明和初始化指针 】
首先,指针声明必须指定指针指向的数据的类型(和数组一样,指针都是基于其他类型的)。例如: int * p_updata;
我们说 p_updata 的类型是 指向int的指针,或int*。可以这样认为,p_updata是指针(地址),而*p_updata是int,而不是指针。
传统上,c程序员使用这种格式:int *ptr; ——这强调 *ptr 是一个int类型的值。
而很多c++程序员使用这种格式:int* ptr; ——这强调 int* 是一种类型,即指向int的指针。
在哪里添加空格对编译器来说没有任何区别,你甚至还可以这样做: int*ptr;
但有一点要知道的是,下面的声明创建的是一个指针(p1)和一个int变量(p2):
int* p1,p2;
对每一个指针变量名,都需要使用一个*。
可以在声明语句中初始化指针。这种情况下,被初始化的是指针,而不是它指向的值。也就是说,下面的语句将 pt (而不是*pt)的值设置为&hig:
int hig=5;
int* pt=&hig;
如下程序演示了如何将指针初始化为一个地址:
vint main()
{
int hig = 5;
int *pt = &hig;
cout << "value of hig =" << hig;
cout << ", address of hig =" << &hig << endl;
cout << "value of *pt =" << *pt;
cout << ", address of pt =" << pt << endl;
}
从中可知,程序将 pt (而不是*pt)初始化为hig的地址。
【指针、数值和指针算术】
指针和数组基本等价的原因在于指针算术和c++内部处理数组的方式。C++将数组名解析为地址。以下程序证明了这一点:
int main()
{
double wages[3] = {10000.0,20000.0,30000.0 };
short stacks[3] = { 3,2,1};
//两种方法得到数组的地址
double *pw = wages; //数组名=地址
short *ps =&stacks[0]; //使用&地址操作符
//输出数组元素
cout<< "pw = " << pw << ", *pw = " << *pw << endl;
pw= pw + 1;
cout<< "指针pw加1:" << endl;
cout<< "pw = " << pw << ", *pw = " << *pw << "\n\n";
cout<< "ps = " << ps << ", *ps = " << *ps << endl;
ps= ps + 1;
cout<< "指针ps加1:" << endl;
cout<< "ps = " << ps << ", *ps = " << *ps << "\n\n";
cout<< "用数组表示法访问两个元素\n";
cout<< "stacks[0] = " << stacks[0];
cout<< ", stacks[1] = " << stacks[1] << endl;
cout<< "用指针表示法访问两个元素\n";
cout<< "*stacks = " << *stacks;
cout<< ", *(stacks + 1) = " << *(stacks + 1) << endl << endl;
//占字节数
cout<< "size of wages array = " << sizeof(wages) << endl;
cout<< "size of pw array = " << sizeof(pw) << endl;
cout<< "size of stacks array = " << sizeof(stacks) << endl;
cout<< "size of ps array = " << sizeof(ps) << endl;
}
在多数情况下,c++将数组名解释为数组第一个元素的地址。整数变量加1后,其值将增加1;但将指针变量加1后,增加的量等于它指向的类型的字节数。
和所有数组一样,wages也存在下面的等式:
wages = &wages = 数组第一个元素的地址
【指针和字符串】
数组和指针的特殊关系可以扩展到C-风格字符串,请看下面的代码:
char flower[10] = “rose”;
cout<< flower <<”s are red\n”;
数组名是第一个元素的地址,因此cout语句中的flower 是包含字符r的char元素的地址。cout认为char的地址就是字符串的地址,因此他打印该地址处的字符,然后继续打印后面的字符,直到遇到空字符为止。总之,如果给cout提供一个字符的地址,则他将从该字符开始打印,直到遇到空字符(\0)为止。
下面的程序演示了如何使用不同形式的字符串:
int main()
{
char animal[20] = "dog";
const char* bird = "flamingo";
char* p;
cout << animal << " and " << bird << endl;
cout << "请输入一种动物:";
cin >> animal;
p = animal; //指针p指向字符串animal
cout << p << endl;
cout << "用strcpy()之前:\n";
cout << animal << " at " << (int *)animal << endl;
cout << p << " at " << (int *)p << endl;
p = new char[strlen(animal) + 1]; //创建一个新内存空间
strcpy(p, animal); //把字符串拷贝到新内存空间,将获得“fox”的两个独立副本
cout << "用strcpy()之后:\n";
cout << animal << " at " << (int *)animal << endl;
cout << p << " at " << (int *)p << endl;
delete[] p;
return 0;
}
请注意下述代码完成的工作:
p = animal; //指针p指向字符串animal
…
cout << animal << " at " << (int *)animal << endl;
cout << p << " at " << (int *)p << endl;
他将生成下面的输出:
一般来说,如果给cout提供一个指针,他将打印地址。但如果指针的类型为char*,则将显示指向的字符串(这也是我们之前一直强调的)。若想要显示的是字符串的地址,则必须要把这种指针类型强制转换为另一种指针类型,如int*(上面的代码就是这样做的)。因此,ps显示的是字符串“fox”,而(int*)ps显示的是该字符串的地址。