看个图片放松一下

优先级之争 * []

image.png
如图,我们在讲这个问题之前 * 解地址运算符 是[]下标运算符 低一等级的

首先我们先明白两个概念

指针数组

指针数组本质上还是一个数组,只不过每个元素里装的都是指针
声明格式: int* p[n];

分析优先级

[] 比 * 高

  1. p 先和[]组合成数组,
  2. int 和* 组合成int * 这个指向整型的指针数据类型
  3. 合起来 就是 指针数组啦

数组指针

数组指针本质上是一个指针,指向的是给定数组长度为变量
声明格式:int (*p)[n];

(*p)优先级高

  1. 这样的话 (*p) 组合成指针
  2. int 和[]再去修饰(*p) ,那么p指向一个长度为n的int 数组

指针类型数据

int* 也是一种类型,就是指向整型的指针哇
int** 也是一种类型,就是指向整型的指针的指针的数据类型。

这是一个很容易弄乱的概念,这里有一篇实例可以看一看
我们经常用指针来访问数组,了解这些是必不可少的。我们可以还会见到更复杂的,同理推即可。

数组名其实就是指针

我们如果为p开辟了空间,我们就可以把它当数组一样访问啦

int* p=new int[6];

访问p第二个格子里面存的数据,我们只需 p[1]即可,无需再次解地址啦
*p[1](这是错误的),因为[]已经帮帮解地址了,在会想一下数组名,是不是数组名就是一个指针呢。

高阶下的指针与数组

其实在前面我们得出了一个结论,数组就是指针,那么高阶数组和指针呢?

一维

int a[5];
int *p=a;

这个无需解释了

二维,指针的指针

#include<iostream>

int main()
{
	int a[5][5];
	int (*p)[5]=a;//
	p[2][3]=3;
	std::cout<<a[2][3]<<" "<<*(*(p+2)+3)<<'\n';//*(*(p+2)+3)与p[2][3]等价
	return 0;
}

运行结果

这里我们发现要想让他们有关联,那么我们声明的指针要比我们的数组低一阶,指向数组的上一阶的基本单位。说起来比较绕,我们就那这个实例来说吧。
如果我们要想指向二维数组 那么我们必须有一个指向一维数组的指针,就是前面提到的数组指针

n维

如果我们要想指向n维数组 那么我们必须开辟一个指向n-1的指针数组。

当然我们一般情况最高都是二维啦。

回到标题,我们用new开辟一个数组空间

二维

const int row,col;//定义指针的长度,宽度
int **p;
//指针的指针,*p指向的数组指针
p = new int* [col]; 
//指向一维数组指针,每个格子里都是一个地址(下一纬度的头地址)
        for (int i = 0; i <col ; i++)
             p[i]=new int[row];
//使p[i]都指向一个整型
        for (int i = 0; i <row ; i++)
            for (int j = 0; j < col; j++)
                p[i][j] = 0;
//赋值

销毁

这里补充一下销毁,我们一定要倒着来 ,先销毁低阶的指针,后销毁高阶的.

for (int i = 0; i <col ; i++)
            delete[] p[i];
        delete[] p;
    }

下面是一片一个2*2数组类的程序,放在这里方便理解。

#include <iostream>
#include<iomanip>

class myArray
{
    int **p; 
public:
    myArray()
    {
        //开辟多维数组
        p = new int *[2]; 
        for (int i = 0; i < 2; i++)
             p[i]=new int;
        for (int i = 0; i < 2; i++)
            for (int j = 0; j < 2; j++)
                p[i][j] = 0;
    }
    myArray(const myArray& t)//拷贝构造函数 不加const报错 
    {
        
        p = new int *[2]; 
        for (int i = 0; i < 2; i++)
             p[i]=new int;
        for (int i = 0; i < 2; i++)
            for (int j = 0; j < 2; j++)
                p[i][j] = t.p[i][j];
    }
    ~myArray()
    {
        for (int i = 0; i < 2; i++)
            delete[] p[i];
        delete[] p;
    }
    friend std::ostream& operator<<(std::ostream& out,myArray& a);
    friend std::istream& operator>>(std::istream& in,myArray& a);
    friend myArray operator+(myArray& a1,myArray& a2);
};

std::ostream& operator<<(std::ostream& out,myArray& a)
{
    for (int i = 0; i < 2; i++)
            {
                for (int j = 0; j < 2; j++)
                    std::cout<<std::setw(5)<<a.p[i][j];
                std::cout<<"\n\n";
            }
    return out;
}
std::istream& operator>>(std::istream& in,myArray& a)
{
    for (int i = 0; i < 2; i++)
            for (int j = 0; j < 2; j++)
                in>>a.p[i][j];

    return in;
}
myArray operator+(myArray& a1,myArray& a2)
{
    myArray  t;
    for (int i = 0; i < 2; i++)
            for (int j = 0; j < 2; j++)
                t.p[i][j]=a1.p[i][j]+a2.p[i][j];
    return t;
}

int main()
{
    myArray a,b;
    std::cin>>a>>b;
    myArray t=a+b;
    std::cout<<t;
    return 0;
}

运行结果

结语

这样我们就很简单的理解了指针这个概念,哎还是感觉没总结好,不理解还可以看一看这一篇

努力成长的程序员