C++中的指针
原创
©著作权归作者所有:来自51CTO博客作者CurryCoder的原创作品,请联系作者获取转载授权,否则将追究法律责任
1.Cpp中的指针
2.什么是指针?
3.C++中使用指针
4.Cpp中指针详解
- C++中与指针有关的概念如下表:
4.1 C++中的NULL指针
4.2 指针的算术运算
- 指针变量中存放的是一个用数值表示另一个变量的地址,可以对指针变量执行算术运算。对指针进行四个算术运算:++ – - +,假设ptr是一个指向地址是1000的整型指针变量,是一个32位整数,对该指针执行算术运算ptr++后,ptr的指向位置是1004。因为ptr每增加一次,它都指向下一个整数位置,即当前位置往后移动4个字节。这个运算在不影响内存位置中实际值的情况下,移动指针到下一个内存位置。如果ptr执向的是一个地址是1000的char型字符,上面的运算会导致指针指向位置1001,因为下一个字符位置是1001。
- 递增一个指针:在程序中使用指针代替数组,因为指针变量可以递增,而数组不能递增,因为数组名是一个指针常量,如下面的例子:
int a[MAX] = {10, 100, 200};
int *pp;
pp = a;
for (int i = 0; i<MAX; i++){
cout << "变量a[" << i << "]的地址是: " << &a[i] << endl;
cout << "变量a[" << i << "]的地址是: " << pp << endl;
cout << "变量a[" << i << "]的值是: " << a[i] << endl;
cout << "通过访问指针变量pp中存放的普通变量的地址来得到数组元素的值: " << *pp << endl;
cout << "------------------------------------------------\n";
pp++; // 移动到下一个位置
}
- 递减一个指针:对指针进行递减运算,即把值减去其指向的数据类型的字节数,如下所示:
pt = &a[MAX - 1];
for (int i = MAX - 1; i >= 0; i--){
cout << "变量a[" << i << "]的地址是: " << &a[i] << endl;
cout << "变量a[" << i << "]的地址是: " << pt << endl;
cout << "变量a[" << i << "]的值是: " << a[i] << endl;
cout << "通过访问指针变量pt中存放的普通变量的地址来得到数组元素的值: " << *pt << endl;
cout << "------------------------------------------------\n";
pt--; // 移动到下一个位置
}
- 指针的比较:指针可以用关系运算符进行比较,如果p1和p2指向两个相关的变量,如同一个数组中的不同元素,则可以对p1和p2进行大小比较。
tt = a;
int j = 0;
while (tt <= &a[MAX - 1]){
cout << "变量a[" << j << "]的地址是: " << tt << endl;
cout << "变量a[" << j << "]的值是: " << a[j] << endl;
tt++;
j++;
}
4.3 指针vs数组
- 指针与数组是密切相关的,在很多情况下两个是可以互换的。例如,通过一个指向数组开头的指针,可以通过使用指针的算术运算或数组的索引来访问数组,如下面例子:
int a[MAX] = {10, 100, 200};
int *pp;
pp = a;
for (int i = 0; i<MAX; i++){
cout << "变量a[" << i << "]的地址是: " << &a[i] << endl;
cout << "变量a[" << i << "]的地址是: " << pp << endl;
cout << "变量a[" << i << "]的值是: " << a[i] << endl;
cout << "通过访问指针变量pp中存放的普通变量的地址来得到数组元素的值: " << *pp << endl;
cout << "------------------------------------------------\n";
pp++; // 移动到下一个位置
}
- 然而,指针与数组并不是完全可以互换的,如下面的例子:
int b[MAX] = {1, 11, 111};
cout << "b = " << b << endl;
cout << "*b = " << *b << endl;
for (int i = 0; i < MAX; i++){
*b = i; // 改变的是数组第一个元素的值
// b++; 数组名是一个指针常量,不能进行修改
*(b + 2) = 555;
}
// 不是说数组内的值不能修改,而是只要b的值(地址)不变,那么相应位置的数值改变了,也不会影响该数组的首地址。
4.4 指针数组
- 引入:一个由3个整数组成的数组
int c[MAX] = {6, 66, 666};
for (int i = 0; i < MAX; i++){
cout << "c[" << i << "]的值是: " << c[i] << endl;
}
- 可能有一种情况是:希望数组存储的是指向int/char或者其他数据类型的指针,下面是一个指向整数的指针数组的声明:
int * ptr[3];
- 把ptr声明为一个数组,由3个整数指针组成。因此,ptr中的每个元素,都是指向int类型的指针,见下面的例子:
int cc[MAX] = {6, 66, 666};
int *pc[MAX]; // 定义一个指针数组
for (int i = 0; i < MAX; i++){
pc[i] = &cc[i]; // 由于pc数组中的每个元素都是指向int类型的指针,所以这里赋值为cc[i]的每个元素的地址
}
for (int i = 0; i < MAX; i++){
cout << "cc[" << i << "]的地址是: " << pc[i] << endl;
cout << "cc[" << i << "] = " << *pc[i] << endl;
}
- 也可以用一个指向字符的指针数组来存储一个字符串列表,如下面例子:
const char *names[MAX] = {
"Curry",
"Harden",
"Durant",
}; // const char * names[MAX]是指针数组,它的本质是存储指针的数组,存储的元素是char类型的指针
for (int i = 0; i < MAX; i++){
cout << "names[" << i << "] = "<< names[i] << endl; // 输出字符串的值
cout << "*names[" << i << "]的值是: " << *names[i] << endl; // 输出指针所指向的字符串的首地址的值
cout << "names[" << i << "]的地址是: " << &names[i] << endl; // 输出指针所指向的字符串的首地址
}
4.5 指向指针的指针(多级间接寻址)
4.6 传递指针给函数
- C++中允许传递指针给函数,只需要简单地声明函数参数为指针类即可,下面的实例是传递一个long型指针给函数,并在函数内改变这个值:
void getSeconds(unsigned long *par){
*par = time(NULL); // 获取当前秒数
}
// 传递指针给函数
unsigned long sec;
getSeconds(&sec);
// 输出实际值
cout << "number of seconds: " << sec << endl;
- 能接收指针作为参数的函数,也可以接收数组作为参数,如下所示:
double getAverage(int *arr, int size){
int i, sum = 0;
double avg;
for (i = 0; i < size; i++)
sum += arr[i];
avg = double(sum) / size;
return avg;
}
int balance[5] = {1, 2, 3, 4, 5};
double avg;
// 传递一个指向数组的指针作为参数
avg = getAverage(balance, 5);
cout << "平均值: " << avg << endl;
4.7 从函数返回指针
- 从函数返回指针,需要声明一个返回指针的函数,如下所示:
int * myFunction(){
语句;
}
- 此外,C++不支持在函数外部返回局部变量的地址,除非定义的是局部变量static变量。
- 返回从函数返回指针的实例如下:
// 要生成和返回随机数的函数
int * getRandom(){
static int r[10];
// 设置种子
srand((unsigned)time(NULL));
for (int i=0; i<10;i++){
r[i] = rand();
cout << "r[" << i << "]=" << r[i] << endl;
}
return r;
}
// 从函数返回一个指针
int *ppg;
ppg = getRandom(); // 调用子函数,从子函数中返回一个指针
for (int i = 0; i < 10; i++)
cout << "*(ppg + " << i << ") = " << *(ppg + i) << endl;
5.指针小结
- 指针的本质是变量,可以是各种数据类型,定义一个指针"*ip",其中"ip"需要赋于一个地址(可以用&符号获取其他变量的地址再赋值给 ip),而"*ip"是一个具体的值,即读取地址后获得的值;&符号的意思是取地址,也就是返回一个对象在内存中的地址, *符号的意思是取得一个指针所指向的对象,也就是如果一个指针保存着一个内存地址,那么它就返回在那个地址的对象。
#include <iostream>
using namespace std;
int main()
{
int var = 20;
int *ip;
ip = &var;
cout << "var的值:";
cout << var << endl;
cout << "变量ip的储存地址:";
cout << ip << endl;
cout << "指针*ip的值:";
cout << *ip << endl;
return 0;
}
-
C++中允许声明指向函数的指针,被称为函数指针。函数指针的声明类似于函数的声明,只不过将函数名变成了(*指针名),定义方式: int (*fp)(int a); // 定义了一个指向函数(这个函数参数仅仅为一个int类型,函数返回值是int类型)的指针fp
int func(int b);
{
cout << b;
return ++b;
}
// 定义一个函数指针
int(*p)(int);
p = func;
// 通过函数指针来调用函数
(*p)(5);