【问题标题】:Find the address of an index in an array in C在C中查找数组中索引的地址
【发布时间】:2014-11-13 01:31:19
【问题描述】:

给定C中数组的定义:int a[2][3][4][5],a[0][0][0][0]的地址是1000地址是什么a[1][1][1][1],假设一个int占用4个字节。

我明白了:

(3*4*5 * 4bytes) + (4*5 * 4bytes) + (5* 4bytes) + 4bytes = 344

344 + 1000 = 1344 a[1][1][1][1]的位置

但我不知道我是否正确。但我的数学对我来说似乎是正确的。

【问题讨论】:

    标签: c arrays memory-address


    【解决方案1】:

    只要打印你会看到的变量的地址!:

    #include <stdio.h>  
    
    int main() {
    
        int a[2][3][4][5];
    
        printf ("Size of int %d\n", sizeof(int));
    
        printf("Adress of the frist element \t%p\n", &a[0][0][0][0]);
        printf("Adress of x element \t\t%p\n", &a[1][1][1][1]);
    
        printf ("In decimal: \t\t\t%d\n", &(a[0][0][0][0]));
        printf ("In decimal: \t\t\t%d\n", &(a[1][1][1][1]));
    
        printf("Difference between the adresses %d", (char *)&a[1][1][1][1] - (char *)&a[0][0][0][0]);
    
    
    
    
        return 0;
    
    }
    

    之后你可以检查你的位置是否正确!

    正如你所见,你的权利!我是334

    【讨论】:

    • 您的第二个printf 提供a[1][1][1][0] 的地址,而不是a[1][1][1][1]。为什么不直截了当地说出你想要做什么并写&amp;a[0][0][0][0]
    • %d 带有指针是有问题的(特别是如果 int 是 32 位而指针是 64 位),考虑使用 uintptr_t
    • 如果我错了,请原谅,但在第一个示例中,是否真的需要所有引用和取消引用?当然&amp;a[0][0][0][0] 只是a
    • @Vality 为了更清晰,我做了它!但你的权利!
    【解决方案2】:

    你的数学是正确的。您可以通过将两个地址相减来检查,但不要忘记指针算法会识别类型大小,因此您必须将地址转换为大小为字节的 char:

    ( char* )&a[1][1][1][1] - ( char* )&a[0][0][0][0]
    

    它给出了字节的差异。然后只需添加起始地址即可获得答案。

    【讨论】:

      【解决方案3】:

      这样的事情很容易检查 (a):

      #include <stdio.h>
      
      int main (void) {
          int a[2][3][4][5];
      
          // Ignore incorrect format specifiers for now.
      
          printf ("%d\n", sizeof(int));
          printf ("%d\n", &(a[0][0][0][0]));
          printf ("%d\n", &(a[1][1][1][1]));
          printf ("%d\n", (int)&(a[1][1][1][1])
                        - (int)&(a[0][0][0][0])
                        + 1000);
      
          return 0;
      }
      

      然后输出是:

      4
      2665056
      2665400
      1344
      

      请注意最终printf 中指向int 值的指针的转换。如果没有这个,1000 将被缩放为int *,从而给出错误的值。

      所以,是的,最重要的是,你的推理是正确的。


      (a)总是情况并非如此,因为 C 语言的某些方面可能因实现(实现指定的行为)或它们想要的任何方式(未定义)而不同行为)。

      幸运的是,数组的布局由标准专门指定的,在C11 6.5.2.1 Array subscripting

      2/ 后缀表达式后跟方括号中的表达式[] 是数组对象元素的下标指定。下标运算符[]的定义是E1[E2]等同于(*((E1)+(E2)))。由于适用于二进制+ 运算符的转换规则,如果E1 是一个数组对象(等效地,指向数组对象的初始元素的指针)并且E2 是一个整数,E1[E2] 指定E2-thE1 元素(从零开始计数)。

      3/ 连续的下标运算符指定多维数组对象的一个​​元素。如果E 是一个维度为i * j * ... * k 的n 维数组(n >= 2),那么E(用作左值以外)将转换为指向(n - 1) 维数组的指针尺寸j * ... * k。如果将一元 * 运算符显式地或作为下标的结果隐式地应用于此指针,则结果是引用的 (n - 1) 维数组,如果用作左值以外的数组,它本身将转换为指针. 由此得出,数组以行优先顺序存储(最后一个下标变化最快)。

      【讨论】:

      • 那个输出看起来很奇怪,2665400 - 2665056 + 1000 不是1086。我想编译器认为您正在尝试进行指针运算。
      • @RedAlert,是的,刚刚注意到了这一点,而且你会认为像我一样拥有 C 的人会预先知道这一点 :-) 已修改以修复。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-02-06
      • 1970-01-01
      • 2014-05-08
      • 2018-07-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多