zoukankan      html  css  js  c++  java
  • 再论数组

    1.什么时候数组和指针相同

         在实际应用中,数组和指针可以互换的情形比不可互换的情形要更为常见,让我们分别考虑“声明”和“使用”这两种情况;数组声明可以分成3种情况:
         1.外部数组的声明(external array)
         2.函数定义(定义是声明的特殊情况,它分配内存空间)
         3.函数参数的声明
         所有作为函数参数的数组总是可以通过编译器转换为指针,在使用数组(在语句或表达式中的引用)时,数组总是可以写成指针的形式,两者可以互换。
     图1 指针和数组何时相同

    数组和指针在编译处理时是不同的,在运行时的表示形式也是不一样的,并可能产生不同的代码。对编译器而言,一个数组就是一个地址,一个指针就是一个地址的地址

    2.c标准中的数组规定

    规则1:"表达式中的数组名"就是指针

            对数组下标的引用总是可以写成“一个指向数组的起始地址的指针加上偏移量”;对数组的引用如a[i]在编译时总是被编译器改成*(a+i)的形式,在表达式中,指针和数组可以互换,因为在编译器里的最终形式都是指针。

       编译器自动把下标值的步长调整到数组元素的大小。如果数组元素的大小是4字节,那么a[i]和a[i+1]在内存中的距离就是4。对起始地址执行加法之前,编译器会负责计算每次增加的步长。这就为什么指针总是有类型限制的,每个指针只能指向一个类型的原因所在:编译器需要知道对指针进行解引用操作时应该取几个字节,以及每个下标的步长应取几个字节

    规则2:c语言把数组下标作为指针的偏移量

    规则3:“作为函数参数的数组名”等同于指针

          在函数形参定义这个特殊情况下,编译器必须把数组形式改成指向数组第一个元素的指针形式,编译器只向函数传递数组的地址,而不是整个数组的拷贝。

    例如:定义函数

    void func(int *ptr){...}
    void func(int ptr[]){...}
    void func(int ptr[20]){...}
    在func函数的调用上,实参是数组和指针都是合法的

    3.数组和指针的可交换性的总结

    1)用a[i]这样的形式对数组进行访问总是被编译器解释为像*(a+i)这样的指针访问。

    2)指针始终是指针。它绝不可以改成数组,你可以用下标形式访问指针,一般都是指针作为函数参数时,而且你知道实际传递给函数的是一个数组。3)把一个数组定义为函数的参数时,可以选择把它定义为数组,也可以定义为指针;不管是哪种,在函数内部获得的都是一个指针。4)在其他所有情况中,定义和声明必修匹配。如果定义了一个数组,在其它文件对它进行声明时也必须把它声明为数组,指针也是如此。

    4.多维数组的内存布局

    在C语言中数组的元素可以是另一个数组,有助于数组的分解,例如声明如下的三维数组:

    int array[2][3][5]

    图 2 整个数组的内存

    图 3 sizeof[i]的内存空间

    图4 sizeof[i][j]的内存空间

    图 5 sizeof[i][j][k]的内存空间

    再如:

    char ch[4][3];

    有人把二维数组看作是排列在一张表格中的一行行的一维数组,如下:

                      图 6 假想的内存分布

    实际的内存分布如下:

    图 7 实际内存分布
          ps:对于二维数组,像图6假想的内存分布有助于平时分析,但实际的内存分布不是这样子的
         在C语言的多维数组中,最右边的下标最先变化,绝大数的语言都是采用这个约定且在堆栈内存朝低地址方向增长;
    例如:
    char b[2][2];


  • 相关阅读:
    数据结构总结(UPDATING......)
    课件例题4.11,4.12
    Luogu P1525 关押罪犯
    Luogu P1540 机器翻译
    Luogu P1313 计算系数
    Luogu P1311 选择客栈
    Luogu P1519 穿越栅栏 Overfencing
    Luogu P2863 [USACO06JAN]牛的舞会The Cow Prom
    Tarjan学习笔记
    Luogu P3393 逃离僵尸岛
  • 原文地址:https://www.cnblogs.com/jinxiang1224/p/8468449.html
Copyright © 2011-2022 走看看