zoukankan      html  css  js  c++  java
  • C语言 二维数组与指针笔记

    今天分析了C语言二维数组和指针的基本理解,感觉有点懵。。。代码记录一下,如果有大神临幸发现哪里有误,欢迎指正~~~

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    //void func(int p[][])  //这样写等同于void func(int **p)   p++移动了四个字节,(*p)++移动了四个字节,不符合二维数组规律
    //{
    //}
    
    
    //列优先输出的函数(即竖着输出)
    void func(int p[][4], int a, int b)  //这样写是正确的,这样写等同于void func(int (*p)[4])   p++移动16个字节,(*p)++移动了4个字节,a和b是为了保持维度,a表示列,b表示行
    {
        for (int i = 0; i < a; i++)
        {
            for (int j = 0; j < b; j++)
            {
                printf("%d
    ", *(*(p + j) + i));
            }
        }
    }
    
    int main()
    {
        int array[3][4] = { { 0, 1, 2, 3 }, { 4, 5, 6, 7 }, { 8, 9, 10, 11 } };
    
        //printf("%d
    ", sizeof(array[0]));  // 结果为16,妈的,array[0]竟然不是指针,而是一个数组的名称,
        //printf("%d
    ", sizeof(array));    //结果48
     func(array, 
    sizeof(array[0]) / sizeof(int), sizeof(array) / sizeof(array[0]));//
    第二个参数是列数,第三个参数为行数
    //array[0]并不是一个变量,是二维数组中第0行的首地址
    //和下面的:      *(p + 0) + 1;    代表int *向后位移了一个位置   道理上应该是相同的。
    
            //在二维数组中*array代表的也是数组的首地址,而一维数组中*array代表的是第一个元素的值
        //printf("%d  %d  %d  %d
    ", array, *array, &array, &array[0][0], array[0]);
    
       //
    printf("%d ", array + 1); //
    printf("%d
    ", array[0] + 1);
            //结果为array + 1  移动了16个字节
            //        array[0] + 1 移动了4个字节
            //可以这样理解,array + 1看成连长,array[0] + 1看成排长,连长每次走一行(即走4个数,14个字节),排长每次走一列(即走一个数,4个字节)
    
    
        //int *p = array;  //指向一维数组的指针
    
       
    //int (*p)[4];
    是一个变相的二级指针
        //p = array;
        //*(p + 0) + 1;    代表int *向后位移了一个位置
    
        //for (int i = 0; i < 4; i++)
        //{
        //    for (int j = 0; j < 3; j++)
        //    {
        //        printf("%d
    ", *(*(p + j) + i));
        //    }
        //}
        //*(p + 0)   代表的是指向第一行的指针。所以*(p + 0) + 1  是指向第一行第二个元素的位置
        //printf("---------------
    ");
    
        //-----------
        //p + 1;   //代表的是排长,每次走一行
        //p[0][0] = *(*(p + 0) + 0);  //代表的是连长,每次走一个数
    
        //printf("%d
    ", *(*(p+1)));  //第一行第0个元素
    
        system("pause");
        return 0;
    }

    分析如下:

    黄色代码部分:输出的地址完全相同,所以二维数组和一维数组的一点区别是:   在二维数组中*array代表的也是数组的首地址,而一维数组中*array代表的是第一个元素的值

    红色代码部分:      相对于黄色代码部分,红色代码结果为:     array + 1 移动了16个字节  , array[0] + 1 移动了4个字节;

      因为array是数组的首地址,而且是一个二维数组,所以array+1  应该是移动一行,即4个数字,array[0]是二维数组的“第一行数组”的首地址,所以+1应该是在第一行数组里面移动指针;

    ( 如果 int  *p = &i;  那么p+1的结果就会移动4个字节,如果 char  *p = &i;  那么p+1的结果就会移动1个字节,  这里其实也是相同的道理,只是不好理解。。。)

    也可以使用排长和连长的例子来理解,把array看成连长,把array[0]看成排长,连长每次审阅,会一行一行的走,排长审阅,则会一排一排的走,所以array(连长)每次走16个字节,array[0]每次走4个字节。

     

    橘黄色代码部分:       定义二级指针的时候,一般会这样定义,int (*p)[4];

    这里有一个“指针数组”和“数组指针”的概念,图示和代码如下:

                指针数组:                                                                                    数组指针

              int *p[5];                                                                           int (*P)[10];

    ImageImage

    #include <stdio.h>
    #include <stdlib.h>
    
    int main()
    {
               //指针数组
               char *s[10];   //是一个数组,该数组中有10个char *指针,每个指针指向一个字符
              printf( "%d
    " ,sizeof (s[0]));  //4
    
               //数组指针
               char (*s1)[10];    //是一个指针变量,该指针变量指向一个char[10];不能指向其他任何char[n]数组
              printf( "%d
    " , sizeof (s1));   //4
    
              system( "pause" );
               return 0;
    }

    所以:int (*p)[4]; 是一个数组指针,指向一个4个元素的数组,

    p = array;    也就是把二维数组的首地址赋给p,array也是一个地址(相当于一个指针,但如果我们用sizeof(array)会发现其实不是一个指针),所以p其实是一个变相的二级指针(你不信的话可以利用**p测试看是否能够取到数组的第一个元素)

    所以    *(p + 0) + 1; 代表int *向后位移了一个位置   也就不难理解了, p是一个二级指针, p+0代表的其实就是第一行数组的首地址。*(p+0) 还是一个指针,  也就是一个int * 类型的变量(指针也是一个变量),*(p + 0) + 1;代表的就是int *向后位置了一个位置

    *(p + 0) 代表的是指向第一行的指针。所以*(p + 0) + 1 是指向第一行第二个元素的位置的指针,*(*(p + 0) + 1 ) 就是第一行第二个元素的值;

    灰色颜色代码的部分:     这样写的原因就是直接把二维数组的维度发过去,因为在接收端函数方是不知道二维数组的维度的,而且这样写以后更改数组的维度的时候,不用更改其他代码。

  • 相关阅读:
    《学习之道》第六章总结
    《学习之道》第六章一心多用
    《学习之道》第六章无视干扰
    《学习之道》第六章番茄工作法
    《学习之道》第六章关注过程,亦培养习惯
    《学习之道》第六章学习方法23与小恶魔较劲
    《学习之道》第六章习惯的部分-信念
    《学习之道》第六章习惯的部分-奖励机制
    《学习之道》第六章习惯的部分-反应程序
    使用Python验证常见的50个正则表达式
  • 原文地址:https://www.cnblogs.com/vczh/p/5811587.html
Copyright © 2011-2022 走看看