指针和 const & 数组

笔记 · 2023-06-25 · 364 人浏览
指针和 const & 数组

  在 C++ 中,指针、const 和数组之间有一些重要的关系。指针和 const 可以用于限定指针的可变性和所指向的值的可变性,而指针可以与数组进行关联,方便对数组进行遍历和操作。


指针和 const

  指针可以和 const 修饰符结合,常见的有两种形式:

  • 一种是指针指向的是一个常量
  • 另一种是指针本身是一个常量

(1)指向常量的指针

  指针指向的是一个常量,所以只能访问数据,不能通过指针对数据进行修改。不过指针本身是变量,可以指向另外的数据对象。这时应该把 const 加在类型前。

const int a = 10, b = 20;

//int* pa = &a;        // 错误,类型不匹配

const int* pa = &a;    // 正确,pa是指向常量的指针,类型为const int*

pa = &b;            // pa可以指向另一个常量

int i = 1024;

pa = &i;             // pa也可以指向变量

*pa = 1000;          // 错误,不能通过pa更改数据对象
// const修饰的是指针,指针指向可以改,指针指向的值不可以更改

  这里发现,pc 是一个指向常量的指针,但其实把一个变量 i 的地址赋给它也是可以的;编译器只是不允许通过指针 pc 去间接更改数据对象。

(2)指针常量(const指针)

  指针本身是一个数据对象,所以也可以区分变量和常量。如果指针本身是一个常量,就意味它保存的地址不能更改,也就是它永远指向同一个对象;而数据对象的内容是可以通过指针改变的。这种指针一般叫做“指针常量”。

  指针常量在定义的时候,需要在星号 * 后、标识符前加上 const

int* const cp = &i;

*cp = 2048;             // 通过指针修改对象的值

cout << "i = " << i << endl;

//cp = &c;              // 错误,不可以更改cp的指向

// 套娃组合:既修饰指针又修饰常量
const int* const ccp = &c;    // ccp是一个指向常量的常量指针
    //cpp = &i; //错误
    //*cpp = 100; //错误
// const修饰的是常量,指针指向不可以改,指针指向的值可以更改

  这里也可以使用两个 const,定义的是“指向常量的常量指针”。也就是说,ccp 指向的是常量,值不能改变;而且它本身也是一个常量,指向的对象也不能改变。

  总结:看 const 右侧后面跟的是指针还是常量, 是指针就是常量指针,是常量就是指针常量。


指针和数组

Paris

作用: 利用指针访问数组中元素

(1)数组名

  用到数组名时,编译器一般都会把它转换成指针,这个指针就指向数组的第一个元素。所以我们也可以用数组名来给指针赋值。

int arr[] = {1, 2, 3, 4, 5};

cout << "arr = " << arr << endl;
cout << "&arr[0] = " << &arr[0] << endl;

int* pia = arr;                        // 可以直接用数组名给指针赋值
cout << "* pia = " << *pia << endl;    // 指针指向的数据,就是arr[0]

  也正是因为数组名被认为是指针,所以不能直接使用数组名对另一个数组赋值,数组也不允许这样的直接拷贝:

int arr[] = {1, 2, 3, 4, 5};
//int arr2[5] = arr;    // 错误,数组不能直接拷贝

(2)指针运算

  如果对指针 pia 做加 1 操作,我们会发现它保存的地址直接加了 4,这其实是指向了下一个 int 类型数据对象:

pia + 1;     // pia + 1 指向的是arr[1]
*(pia + 1);  // 访问 arr[1]

  所谓的“指针运算”,就是直接对一个指针加/减一个整数值,得到的结果仍然是指针。新指针指向的数据元素,跟原指针指向的相比移动了对应个数据单位。

(3)指针和数组下标

  在 C 学习中就知道,数组名 arr 其实就是指针。这就带来了非常有趣的访问方式:

*arr;          // arr[0]
*(arr + 1);     // arr[1]

  这是通过指针来访问数组元素,效果跟使用下标运算符 arr[0]arr[1] 是一样的。进而我们也可以发现,遍历元素所谓的“范围 for 循环”,其实就是让指针不停地向后移动依次访问元素。

for (int num : arr)
    cout << num << '\t';

(4)指针数组和数组指针

  指针和数组这两种类型可以结合在一起,这就是“指针数组”和“数组指针”。

  • 指针数组:一个数组,它的所有元素都是相同类型的指针
  • 数组指针:一个指针,指向一个数组的指针
int arr[] = {1, 2, 3, 4, 5};

int* pa[5];        // 指针数组,里面有5个元素,每个元素都是一个int指针

int(* ap)[5];      // 数组指针,指向一个int数组,数组包含5个元素

cout << "指针数组pr的大小为:" << sizeof(pa) << endl;    // 40

cout << "数组指针ap的大小为:" << sizeof(ap) << endl;    // 8

pa[0] = arr;           // pa中第一个元素,指向arr的第一个元素

pa[1] = arr + 1;       // pa中第二个元素,指向arr的第二个元素

ap = &arr;             // ap指向了arr整个数组

cout << "arr =" << arr << endl;

cout << "* arr =" << *arr << endl;        // arr解引用,得到arr[0]

cout << "arr + 1 =" << arr + 1 << endl;

cout << "ap =" << ap << endl;

cout << "* ap =" << *ap << endl;          // ap解引用,得到的是arr数组

cout << "ap + 1 =" << ap + 1 << endl;

  这里可以看到,指向数组 arr 的指针 ap,其实保存的也是 arr 第一个元素的地址。arr 类型是 int*,指向的就是 arr[0] ;而 ap 类型是 int(*)[5],指向的是整个 arr 数组。所以 arr + 1,得到的是 arr[1] 的地址;而 ap + 1,就会跨过整个 arr 数组。


学习链接

cpp
Theme Jasmine by Kent Liao

本网站由 又拍云 提供CDN加速/云存储服务

鄂ICP备2023005457号    鄂公网安备 42011302000815号

欢迎来自 * · * 的用户