C/C++ 一维/二维 数组与指针之间的小结

首先我抛出下面的问题,读者看一下,如果您全知道是什么意思,那么这篇文章对您毫无帮助,笔者也是一个小菜鸟,只是最近在复习C的基础,突然就把以前困惑我的难题想通,特此写下这篇博客,不求帮到人,只求以后我可以快速的复习。

仔细观察下面代码中的问题并观察输出信息

#include <QDebug>

///一维数组
///问题1:为什么a1不能自增(报语法错误,根本编译不过去),而p1却可以自增呢?
///问题2:为什么a1和&a1的输出值是一样的呢?
void linearArray()
{
    int a[3] = {1277,2,3};
    int *p = a;
    p++;
    //a1++;
    qDebug() << a << &a << *p << *a;

/*
    0x66f918 0x66f918 2 1277
*/
}


///二维数组
///问题1:为什么 sizeof(a)的输出结果是48?
///问题2:为什么下面的第二条输出语句输出的内容全部一样?并且他们都有什么含义
///问题3:为什么第四条输出语句会是666 和 4?
///问题4:int * p3 = a;为什么会报错,为什么必须加强制类型转换后才能编译过去:int * p3 = (int*)a,以及为什么p3+=2后的输出是777?
void twoDimensionalArray()
{
    int a[3][4];
    a[0][0] = 555;
    a[0][1] = 666;
    a[0][2] = 777;
    a[1][0] = 888;
    qDebug() << sizeof(a);

    qDebug() << a << &a << a[0] << &a[0] << *a;

    qDebug() << sizeof (a[0]) << sizeof (*a);

    int * p2 = a[0];
    p2++;
    qDebug() << *p2 << sizeof(a[0])/sizeof(int);

    //int * p3 = a;语法错误?
    int * p3 = (int*)a;
    p3 += 2;//相当于两次自增
    qDebug() << *p3;

/*
输出信息:
    48
    0x12ffb9c 0x12ffb9c 0x12ffb9c 0x12ffb9c 0x12ffb9c
    16 16
    666 4
    777
*/
}

int main(int argc, char *argv[])
{
    linearArray();
    //twoDimensionalArray();
}

首先,我们先说一维数组:

        可能了解c语言的同学都知道,在c语言中数组名是数组的首地址很多人都知道数组名不可以自增,但是将它赋值给一个与它元素同类型的指针后就可以自增了(例如上面注释掉的a1++语句和p1++语句)。

那是因为 数组名在当前函数(定义数组的这个函数),它的值虽然是数组的首地址,但是他的(数组名)类型并不是一个指针,类型就是一个数组!准确来说你甚至可以把它理解为一个常量!这也就解释了为什么在当前函数内  执行{sizeof(数组名)➗sizeof(数组元素类型)}  可以得到数组元素的个数,因为他压根就不是一个指针,是一个常量,只不过这个常量的值是它的首地址,这个常量的步长(其实步长不准确,步长还是站在指针的角度上去说,但是会好理解)是它完整的size。如果你对常量进行自增操作的话,是不符合逻辑的,i++可以,但是3++就不可以,就是这么个道理。

ps:数组名做参数传递后退化为数组第一个元素的地址。但sizeof并不是函数,而是运算符,所不用担心退化为指针)

之所以a1数组名赋值给指针p1之后就可以自增了,其实它赋值给的是数组里第一个元素的首地址,只不过第一个元素的首地址恰恰和数组的首地址相同罢了。而p1所指向的元素的类型的size就是p1的步长,所以p1++后由第一个元素指向了第二个元素。

int * p1 = a1;大家常说是把数组的首地址赋值给指针p1,这样说其实根本就不准确,应该说"将这个指针的第一个元素的地址赋值给p这个指针"更准确。首先我们知道a1这个常量的值是一个地址,他只是把这个地址赋值给了int类型的指针,而int的步长就是数组单个元素的步长,所以应该说将这个指针的第一个元素的地址赋值给p

至于&a就是数组指针,把a理解为一个整体,而不是一个指针,&a就是数组指针了。因为a的地址也是数组的首地址,所以输出一样,只不过步长是整个数组的步长。

为什么*a会输出数组的第一个元素呢?因为上面都说数组名在该函数内不是一个指针,而是一个整体的数组,那么*数组名为什么会得到第一个元素的值呢?在这里简单的说一下"*"在数组中的作用,它用在数组名前是叫做取值符,专门去数组的第一个元素的值。也就是说*a == a[0],之所以抛出这个观念,是怕待会儿二维数组绕晕了(好久没弄c语言了,我都忘记了*在数组中的作用,特此写出来)。

在掌握了上面所属的一维数组的特性后,我们再来看二维数组:

问题一:

         和一维数组一样,参考上面的一维数组

问题二:

        a: a是数组名,数组名的值是该数组的首地址,所以输出数组的首地址。但是a的类型是一个数组,不是指针。

        &a: 就是一个数组指针,步长是整个二维数组的步长。可以参考上面的一维数组

        a[0]:就是a的第一个元素(也是一个数组)的数组名。这也就解释了qDebug() << sizeof (a[0]);输出为什么是16。

        &a[0]:上面已经说过了,你可以把a[0]是一个数组名,那么&a[0]就是表示a[0]这个数组的第一个元素的地址,这也就正好解决了还未解释的问题三

        *a:上面已经说过,可以看上面一维数组对*的解释,*a的就是表示第一个一维数组的数组指针,也就是说这里的a你把它看成一维数组就可以,而*a就是这个一维数组的数组名。

        换算成一维数组后,这就很容易理解了,*a == a[0],也就解释了第三条的输出信息

问题四:

        因为类型都不匹配,所以肯定赋值错误,一个是整形的指针,一个是数组类型。

        当对数组名做了强制类型转换后,数组名代表着的是数组的首地址,也就相当于把数组的第一个元素的地址赋值给了指针p3,这个指针的步长就是整形的步长,所以加了两步后输出的是777

        

猜你喜欢

转载自blog.csdn.net/qq_25704799/article/details/127399223