C++指针介绍

指针(Pointer),从英文字面上理解就是一个指向某一物件的东西,在程序中就是指向数据的地址Address。

1. 指针的声明

在变量类型名和变量名之间加上星号 * ,星号尽量靠近变量名,如下列代码中的 *intPtr1*intPtr2,不然很容易在声明多个指针的时候遗漏后面变量名的星号,如 intPtr4,仅仅声明了一个整形变量。

int *intPtr1, *intPtr2;
int* intPtr3, intPtr4;

在声明指针时一定要初始化指针,如果没有初始化,他可能指向一个未知的地址。

2. 指针的类型

指针的类型表示了指针指向的地址所存储的数据类型,如果需要将 int * 指针转换为 float * 指针,那么程序也只是将数据重新解读为浮点型数据。

void *指针只是代表一个地址,不知道它所指向的数据类型,但可以重新定义它所指向的数据类型。

3. 指针的基本操作

解引用*

获取指针所指向的地址中的数据。
在声明时,*变量名 表示该变量作为一个指针;在其他时刻,*变量名 表示该指针指向的地址中的数据。

取地址&

获取变量的内存地址,并将其赋值给相应的指针

4. 指针的算数操作

指针与整形的算数操作不同于一般的数字加减,而是与指针类型绑定的,指针的算数操作是在当前指针所指向的地址往前或往后移动k个指针类型长度的地址,计算后的指针不一定会指向具有有效数据的地址,所以在进行指针算数操作的时候需小心。

  • 数组名可以看作是指向数组第一个元素的指针,指针的各种操作都适用于数组名,但是数组名不能被重新赋值,因为数组是静态的,数组名代表了当前作用域唯一的一个数组,不可能像指针那样指向其他地址。

指针之间的相减操作返回的是指针地址之间的距离,并且是分正负的,这个距离也与指针类型相绑定。

  string str[] = {
    
     "1","2","3" };
  //取地址
  string *s1 = &str[0];
  string *s2 = &str[1];
  //解引用
  cout << s1 << ' ' << *s1 << endl;
  cout << s2 << ' ' << *s2 << endl;
  //算数操作
  cout << s1 + 1 << ' ' << *(s1 + 1) << endl;
  cout << s2 - s1 << ' ' << s1 - s2 << endl;  //1  -1

指针之间不能相加,因为没有意义。

4. const指针

指向const对象的指针const T *ptr1

ptr1指向的地址中的数据不能更改,但是它本身指向的地址可以更改;

const指针T *const ptr2

ptr2指向的地址不能修改,可以修改地址中保存的数据

指向const对象的const指针const T *const ptr3

ptr3指向的地址不能修改,该地址中的数据也不能更改

  int numA = 3;
  //不能修改数据,能改指针的地址
  const int* ptr1 = &numA;
  //*ptr1 = 8;
  ptr1 = &numA + 1;
  
  //能修改数据,不能改指针的地址
  int* const ptr2 = &numA;
  *ptr2 = 9;
  //ptr2 = &numA + 1;
  
  //不能修改数据,也不能改指针的地址
  const int* const ptr3 = &numA;
  //*ptr3 = 9;
  //ptr3= &numA + 1;

5. 指针数组和数组指针

  • 指针数组T *ptrArr[size],ptrArr是一个数组,数组中的每一个元素都是指针,指针类型是**T*,可以使用*(ptrArr[i])**来读取数组的元素;

  • 数组指针T (*arrPtr)[size],arrPtr指向某一个数组,需要把数组的地址赋值给arrPtr,解引用后就相当于数组,可以使用**(*arrPtr)[i]**来读取数组的元素。

int num[5] = {
    
     1,2,3,4,5 };
//指针数组:元素是指针的数组
int* ptrArr[5] = {
    
     &num[0],&num[1],&num[2],&num[3],&num[4] };
for (int i = 0; i < 5; ++i) {
    
    
  cout << ptrArr[i] << ':' << *(ptrArr[i]) << ' ';
}; cout << endl;

//数组指针:指向数组的指针
int(*arrPtr)[5] = &num;
for (int i = 0; i < 5; ++i) {
    
    
  cout << ptrArr[i] << ':' << (*ptrArr)[i] << ' ';
}; cout << endl;

6. 指针的指针

指针可以指向任何变量或对象,当然也可以指向指针。
指针的指针在声明时,使用 ** 来表示指针指向的指针类型。指针的指针一般用于函数传参数时修改传入的指针。

const_cast和reinterpret_cast

  • const_cast:修改类型的const或volatile属性,返回一个指向非const对象的指针或引用,此时可以通过该指针或引用改变其数据。
    int numA = 3;
    const int* ptr1 = &numA;
    int* ptr2 = const_cast<int*>(ptr1);
    
    const int numB = 3;
    int& numb = const_cast<int&>(numB);
    
  • reinterpret_cast:对变量的数据类型进行改变

7. 指针的一些应用

使用指针对两个数组进行排序


void sortPtr(int rNum, int* a, int aNum, int* b, int bNum) {
    
    
  int* p, * q;
  int* r = (int*)malloc((aNum + bNum) * sizeof(int));
  int* res = r;

  for (p = a, q = b; p < a + aNum && q < b + bNum;) {
    
    
    if (*p > *q) {
    
    
      *r++ = *q++;
    }
    else {
    
    
      *r++ = *p++;
    }
  }
  if (p < a + aNum) {
    
    
    for (; p < a + aNum;)
      *r++ = *p++;
  }
  else if (q < b + bNum) {
    
    
    for (; q < b + bNum;)
      *r++ = *q++;
  }
  for (r = res; r < res + aNum + bNum; ++r) {
    
    
    cout << *r << ' ';
  }
  cout << endl;
}

使用指针遍历数组

//遍历数组时,要知道该数组的长度,以免指针超出数组的范围,导致读取数据失败
void testStr(string* p, int size) {
    
    
  for (int i = 0; i < size; ++i) {
    
    
    cout << p << endl;
    ++p;
  }
}

//遍历字符数组时,
void testChar(const char* p) {
    
    
  while (*p) {
    
    
    cout << *p << endl;
    ++p;
  }
}

猜你喜欢

转载自blog.csdn.net/qq_33021529/article/details/127501745