指针与数组

1.通过数组和下标实现的表达式可以等价的通过指针和偏移量实现。

例如:

int a[]=  {1,4,66,8};

*p = a;

p = &a[0];//和上面一句等价

*(p+1) 和a[1]和*(a+1)是等价的

a+1和&啊&a[1]也是等价的。

2.数组作为函数参数在传参时会自动退化为普通指针

int Srlen(char string[]);

在此函数中若调用系统的字符串长度函数sizeof会发现算不出正确的字符串长度

int Size(char string[])
{
    return sizeof(string);
}


int _tmain(int argc, _TCHAR* argv[])
{
    char pStr[] = {'a','b'};

     cout<<sizeof(pStr)<<endl;
     cout<<Size(pStr)<<endl;

     return 0;

}

得出结果为2,4

数组是一个完备的变量类型,有名字、大小、地址,只不过名字和它的首地址一样罢了,所以用sizeof对数组名

进行计算时算出的是实际数组的大小,而不是指针大小。

3.c/c++默认的是值传递,这个是临时想起来的,也放到这篇里了

double *p = NULL;
fun(p);
if (p == NULL)
{
    cout<<"p not changed"<<endl;
}
else
{
    cout<<"p changed"<<endl;
}

结果为:p not hanged

如果想要改变指针的值还是要址传递参数,这里很容里犯错。下面是正确的做法

double* fun(double **p)
{
    *p = new double;
    return *p;
}


int _tmain(int argc, _TCHAR* argv[])
{
    double *p = NULL;
    fun(&p);
    if (p == NULL)
    {
        cout<<"p not changed"<<endl;
    }
    else
    {
        cout<<"p changed"<<endl;
    }
   
    getchar();
    return 0;
}

4.二维数组的等价访问方式

数组名是一个const指针。

再次强调

数组是一个完备的变量类型,有名字、大小、地址,只不过名字和它的首地址一样罢了,所以用sizeof对数组名

进行计算时算出的是实际数组的大小,而不是指针大小。也正是因为如此,指向数组的指针指向指针有些不一样

最明显的不同就是表现在指针进步的时候我们知道指针在++进行运算的时候,跨越的实际地址取决于指针指向的

数据类型。例如在32位字长机器中指向int型数据跨越的实际地址是4,指向指针类型也是4.指向数组类型的时候,

跨越的实际地址就是数组的长度了。

int a[3][3] = {1,2,3,4,5,6,7,8,9};

下面三种初始化或者复制方式都会编译出错:

int **p = a;
int *p = NULL;
p = &a;
下面两个是正确的:

p = &a[0][0];

int (*q)[3] = a;  //指向含有三个元素的数组的指针,下面会介绍

再看看用这两个正确的方式如何访问数组元素

遍历:

//用p来遍历二维数组
for (int i = 0;i < 12;i++)
{
    cout<<*(p++)<<endl;
}

//用q来遍历二维数组
for (int i = 0;i < 4;i++)
{
    for (int j = 0;j < 3;j++)
    {
        cout<<q[i][j]<<endl;
    }
}


看看下面输出的是什么:

for (int i = 0;i < 4;i++)
{
    cout<<q[i]<<endl;//这里i++或者q++一次就是移动了三个整形元素数组的空间
}

是a[0][0]、a[1][0]、a[2][0]、a[3][0]的地址

下面就很清楚了:

for (int i = 0;i < 4;i++)
{
cout<<*q[i]<<endl;
}

输出的是a[0][0]、a[1][0]、a[2][0]、a[3][0]的值

首地址a也可以像q一样访问数组元素:

int a[4][3] = {1,2,3,4,5,6,7,8,9,10,11,12};

for (int i = 0;i < 4;i++)//a++有一样的效果
{
    cout<<a[i]<<endl;
    cout<<*a[i]<<endl;
}

输出:

4G4N_Y)6K}__8T{(7@I6G2Q

看看下面代码的输出

int a[4][3] = {1,2,3,4,5,6,7,8,9,10,11,12};

for (int i = 0;i < 4;i++)
{
    for (int j = 0;j < 3;j++)
    {//输出每一个元素的地址和值
        cout<<&a[i][j]<<" "<<a[i][j]<<endl;;
    }
}

for (int i = 0;i < 4;i++)
{
    for (int j = 0;j < 3;j++)
    {
        cout<<((*a+i)+j)<<endl;
        cout<<(*a+i+j)<<endl;      //这就相当于用*a取得首地址,后面再加就相当于是在处理一维数组指针,跟前面的p一样
        //cout<<*((*a+i)+j)<<endl;
    }
}

输出:

D%9{O6{Z8TG`S_P419B))XS

for (int i = 0;i < 12;i++)
{
    //从头到尾遍历每个元素的地址和值
    cout<<(*a+i)<<"  "<<*(*a+i)<<endl;
}

输出:

GSB(UVV0A)RG3048RWH$~C7

5.如何new一个二维数组(动态创建二维数组)

int row = 0;
int column = 0;
cin>>row>>column;
int **p = new int*[row];
int k = 1;

for (int i = 0;i < row;i++)
{
    p[i] = new int[column];
    for (int j = 0;j < column;j++)
    {
        p[i][j] = k++;
    }
}

int *q = &p[0][0];
for (int i = 0;i < row*column;i++)
{
    //因为此处p这个二维数组是new了两次创建的,里面的元素不是像a[4][7]一样在内存中
    //顺序排列的,所以用这种方法无法正常打印出二维数组的值
    cout<<(q+i)<<endl;
    cout<<*(q+i)<<endl;
}

//下面是一种遍历动态创建的二维数组的正确方法
for (int i = 0; i < row;i++)
{
    for (int j = 0; j < column;j++)
    {
        cout<<p[i][j]<<endl;
    }
}

上面代码运行结果如下:

image

6.指针数组与数组指针

//()的优先级高,首先说明q是一个指针,指向一个整型的一维数组,这个数组的长度为4。
int (*q)[4] = a;//指向含有4个元素的数组的指针,q++每次移动一行

//[]的优先级高,先与p结合成一个数组,再由int*说明这是一个整型指针数组,它有3个整数指针类型的数组元
int *p[3] = {&a[0][2],&a[1][0],&a[2][0]};//指针数组,顾名思义就是存放指针的数组,就像定义普通数组一样

生命在于折腾,生活就是如此的丰富多彩
原文地址:https://www.cnblogs.com/Mr-Zhong/p/4138259.html