C++指针

指针与数组

参考:C++ 指针 vs 数组 | 菜鸟教程 (runoob.com)
指针和数组在很多情况下是可以互换的。例如,一个指向数组开头的指针,可以通过使用指针的算术运算或数组索引来访问数组。例子如下:

#include <iostream>
 
using namespace std;
const int MAX = 3;
 
int main ()
{
   int  var[MAX] = {10, 100, 200};
   int  *ptr;
 
   // 指针中的数组地址
   ptr = var;
   for (int i = 0; i < MAX; i++)
   {
      cout << "var[" << i << "]的内存地址为 ";
      cout << ptr << endl;
 
      cout << "var[" << i << "] 的值为 ";
      cout << *ptr << endl;
 
      // 移动到下一个位置
      ptr++;
   }
   return 0;
}

编译结果为:

var[0]的内存地址为 0x7fff59707adc
var[0] 的值为 10
var[1]的内存地址为 0x7fff59707ae0
var[1] 的值为 100
var[2]的内存地址为 0x7fff59707ae4
var[2] 的值为 200

但是在下面的情况下,指针与数组不能互换。

#include <iostream>

using namespace std;
const int MAX = 3;

int main()
{
    int var[MAX] = {10, 100, 200};
    cout << "var:" << var << endl;
    for (int i = 0; i < MAX; i++)
    {
        *var = i; // 这是正确的语法
        cout << "var[" << i << "] = " << *var << endl;
        cout << "var:" << var << endl;
        // var++;       // 这是不正确的
    }
    return 0;
}

编译输出:

var:0xbc251ff6e0
var[0] = 0
var:0xbc251ff6e0
var[1] = 1
var:0xbc251ff6e0
var[2] = 2
var:0xbc251ff6e0

原因:
在上述的代码片段中,var 是一个整型数组。对于数组来说,var++ 是不合法的,因为数组名 var 是一个常量指针,它的值(也就是数组第一个元素的地址)是不能被改变的。
在 C++ 中,数组名是一个指向数组第一个元素的常量指针。这意味着你不能改变这个指针的值,也就是说你不能使它指向数组的其他位置。因此,尝试对数组名执行递增 (++) 或递减 (--) 操作都是非法的。
纠正:
如果你想遍历数组的元素,你可以使用一个单独的指针变量,然后使这个指针递增或递减。例如:

int var[3] = {1, 3, 5};
int *ptr = var;
for(int i = 0; i < 3; i++) {
    cout << *ptr << endl;
    ptr++;  // 这是正确的
}

在这个例子中,ptr 是一个可以改变的指针,所以 ptr++ 是合法的。
利用指针的形式改变数组值
由于一个数组名对应一个指针常量,只要不改变数组的值,仍然可以用指针形式的表达式。把 var[2]赋值为 500 的代码如下:

*(var + 2) = 500;

多级指针

指向指针的指针是一种多级间接寻址的形式,或者说是一个指针链。指针的指针就是将指针的地址存放在另一个指针里面。
通常,一个指针包含一个变量的地址。当我们定义一个指向指针的指针时,第一个指针包含了第二个指针的地址,第二个指针指向包含实际值的位置。
多级指针的申明为:

int **var;

举例:

#include <iostream>

using namespace std;

int main()
{
    int var;
    int *ptr;
    int **pptr;

    var = 3000;

    // 获取 var 的地址
    ptr = &var;

    // 使用运算符 & 获取 ptr 的地址
    pptr = &ptr;

    // 使用 pptr 获取值
    cout << "var 值为 :" << var << endl;
    cout << "*ptr 值为:" << *ptr << endl;
    cout << "**pptr 值为:" << **pptr << endl;

    cout << "原始地址:" << endl;
    cout << "var 的地址为 :" << &var << endl;
    cout << "ptr 的地址为:" << ptr << endl;
    cout << "pptr 的地址为:" << pptr << endl;
    var++;
    cout << "改变var地址后的地址:" << endl;
    cout << "var 的地址为 :" << &var << endl;
    cout << "ptr 的地址为:" << ptr << endl;
    cout << "pptr 的地址为:" << pptr << endl;
    ptr++;
    cout << "改变ptr地址后的地址:" << endl;
    cout << "var 的地址为 :" << &var << endl;
    cout << "ptr 的地址为:" << ptr << endl;
    cout << "pptr 的地址为:" << pptr << endl;

    return 0;
}

编译运行的结果为:

var 值为 :3000
*ptr 值为:3000
**pptr 值为:3000
原始地址:
var 的地址为 :0x2394dff8f4
ptr 的地址为:0x2394dff8f4
pptr 的地址为:0x2394dff8e8
改变var地址后的地址:
var 的地址为 :0x2394dff8f4
ptr 的地址为:0x2394dff8f4
pptr 的地址为:0x2394dff8e8
改变ptr地址后的地址:
var 的地址为 :0x2394dff8f4
ptr 的地址为:0x2394dff8f8
pptr 的地址为:0x2394dff8e8