• C语言二位数组的深入理解


    先上一段C语言代码:

    #include <stdio.h>
    
    int cal[3][3]=
    {
        {1,2,3},
        {4,5,6},
        {7,8,9}
    };
    
    int main()
    {
        int i=0; 
        int j=0;
        int num = 0;
        
        //printf the values of cal[0] and cal[1]
        printf("%d:\n",++num);
        for(i=0; i<3; i++)
            printf("0x%0x\n",cal[i]);
            
        printf("%d:\n",++num);
        for(i=0; i<3; i++)
            printf("0x%0x\n",cal+i);
            
        printf("%d:\n",++num);
        for(i=0; i<3; i++)
            printf("0x%0x\n",&cal[i]);    
            
        printf("%d:\n",++num);    
        for(i=0; i<3; i++)
            printf("0x%0x\n",*(cal+i));    
            
        printf("%d:\n",++num);
        for(i=0; i<3; i++)
            printf("0x%0x\n",&cal+i);        
            
        printf("%d:\n",++num);
        for(i=0; i<3; i++)
            printf("0x%0x\n",&cal[0][i]);
            
        printf("%d:\n",++num);
        for(j=0; j<3; j++)    
            for(i=0; i<3; i++)
                printf("0x%0x\n",*(cal+j)+i);
        
        printf("%d:\n",++num);
        for(j=0; j<3; j++)
        {
            for(i=0; i<3; i++)
            {
                printf("%d ",*(*(cal+j)+i));        
            }
            putchar('\n');    
        }    
        
        printf("%d:\n",++num);
        for(j=0; j<3; j++)
        {
            for(i=0; i<3; i++)
            {
                printf("0x%0x\n",&cal[j]+i);        
            }
        }    
        
        printf("%d:\n",++num);
        for(j=0; j<3; j++)
        {
            for(i=0; i<3; i++)
            {
                printf("0x%0x\n",cal[j]+i);        
            }    
        }
        printf("%d:\n",++num);
        for(j=0; j<3; j++)
        {
            for(i=0; i<3; i++)
            {
                printf("%d ",*(cal[j]+i));        
            }
            putchar('\n');    
        }
        
        printf("%d:\n",++num);
        printf("0x%0x\n",&cal);
        printf("0x%0x\n",cal);
        printf("0x%0x\n",*cal);
        printf("0x%0x\n",**cal);
        return 0;
    }
    
    运行结果如下:

    1:
    0x402000
    0x40200c
    0x402018
    2:
    0x402000
    0x40200c
    0x402018
    3:
    0x402000
    0x40200c
    0x402018
    4:
    0x402000
    0x40200c
    0x402018
    5:
    0x402000
    0x402024
    0x402048
    6:
    0x402000
    0x402004
    0x402008
    7:
    0x402000
    0x402004
    0x402008
    0x40200c
    0x402010
    0x402014
    0x402018
    0x40201c
    0x402020
    8:
    1 2 3
    4 5 6
    7 8 9
    9:
    0x402000
    0x40200c
    0x402018
    0x40200c
    0x402018
    0x402024
    0x402018
    0x402024
    0x402030
    10:
    0x402000
    0x402004
    0x402008
    0x40200c
    0x402010
    0x402014
    0x402018
    0x40201c
    0x402020
    11:
    1 2 3
    4 5 6
    7 8 9
    12:
    0x402000
    0x402000
    0x402000
    0x1
    数组的定义即初始化这里不说了,在C语言了多维数组是以“数组的数组”的形式来实现的,所以一开始我们有点迷糊,以为在内存里也是以
    {1,2,3}
    {4,5,6}
    {7,8,9}
    来存放的,和以为和excel的表格一样;其实不然(我也看了C专家编程的C陷阱与缺陷两本书)。
    1,2,3,4,5,6,7,8,9这个元素是以连续的地址存放的,下面的的形式可能更好理解:
    ...1,2,3|4,5,6|7,8,9...
    数组cal[3]里有3个元素,每一个元素又是由3个整形元素构成的数组。
    在这里,数组名cal是一个常量,我们是不能对其赋值的,他的值为首元素1的地址,而&cal是整个数组的地址,其值和cal相等,即&cal=cal但意义却不同,对其进行相应的运算所得到的结果大不一样:
    cal+i=&cal[i];
    &cal+i却不等于cal[i]

    cal+i(i=0,1,2)为:
    0x402000  
    0x40200c  
    0x402018
    &cal+i(i=0,1,2)为:
    0x402000  
    0x402024  
    0x402048  
    各位要注意:整个数组的大小为:3*3*4(sizeof(int))=36(十六进制为:0x00-0x23(咦!~~不是0x24(⊙o⊙)哦)),&cal+1的值为0x402024,&cal+1的值为0x402048,说明这时候(i=1、2)的操作已经超出了我们所定义的数组范围了。而且每一个都是一个和cal数组一样大的数组,只是他们的值是未定义的。
    但是*(cal+i)的各个值为什么和前面几个的是一样呢?我也嘀咕着呢。。
    我看着其实*(cal+i)=cal[i],因为cal+i=&cal[i];所以两边分别加*(解引用)号,得:
    *(cal+i)=*&cal[i];--> *(cal+i)=cal[i];也就是为了后面的*(*(cal+j)+i)做铺垫的。

    next就是&cal[j]+i的来源了:
    &cal[j]+i:
    j=0
    0x402000    i=0
    0x40200c    i=2
    0x402018    i=3
    j=1
    0x40200c    i=0
    0x402018    i=2
    0x402024    i=3
    j=2
    0x402018    i=0
    0x402024    i=2
    0x402030    i=3
    上面的(i和j调换了一下,不过不妨碍理解的)
    &cal[j]和cal[j]有事不一样的,对其进行操作以后不同的结果。
    1、&cal[j]+i就是在&cal[j]的地址基础上再加上i个拥有3个整型数组的大小的地址跨度,0就是不加,1就是加一个,以此类推。。。就会得到上面的结果了。
    2、cal[j]+i就是在cal[j]的地址基础上再加上i个整型数组的大小的地址跨度,0就是不加,1就是加一个,以此类推。。。就会得到上面的结果了。
    cal[j]+i:
    j=0
    0x402000    i=0
    0x402004    i=2
    0x402008    i=3
    j=1
    0x40200c    i=0
    0x402010    i=2
    0x402014    i=3
    j=2
    0x402018    i=0
    0x40201c    i=2
    0x402020    i=3

    那么解引用*之后(即*(cal[j]+i)),得到:
    11:
    1 2 3
    4 5 6
    7 8 9
    其实*(cal[j]+i) = *(*(cal+j)+i)的;而(cal[j]+i) = *(cal+j)+i。
    完。。。


    有些的不好的地方,大家多多指教。。O(∩_∩)O哈哈~





  • 相关阅读:
    将自己数据转化为cifar10支持的lmdb
    python实现cifar10数据集的可视化
    Python OS 文件/目录方法
    象棋AI算法(二)
    象棋AI算法(一)
    围棋人机大战中阿尔法狗原理解析,左右互搏,青出于蓝而胜于蓝?
    电脑开机停留在主板设置界面,进不了系统
    哪一种编程语言适合人工智能?
    BIOS设置图解教程-看完就没有不明白的了
    关于AndroidStudio的打包数字签名以及多渠道发布
  • 原文地址:https://www.cnblogs.com/CodeWorkerLiMing/p/12007722.html
Copyright © 2020-2023  润新知