【问题标题】:Figuring out addresses in C [closed]找出C中的地址[关闭]
【发布时间】:2012-11-12 06:04:20
【问题描述】:

我正在尝试学习如何在 C 中计算地址。对于下面的代码,假设它是在 32 位小端机器上编译的。

struct {
    int n;
    char c;
} A[10][10];

假设 A[0][0] 的地址是 1000(十进制),那么 A[3][7] 的地址应该是多少?任何帮助表示赞赏!

【问题讨论】:

  • 你的意思是&A[0][0]...
  • 你应该在一个真正的程序中尝试一下。详细信息是编译器、操作系统、ABI 和指令集特定的。您可能需要在 GCC 中使用 offsetof 和 __alignof__ 和 sizeof。
  • 为什么不编译它,打印地址,然后弄清楚编译器是如何布局的?
  • 最有可能的是,该结构将被填充到使用的最大数据类型的最近类型边界。这里它是 int,所以 A 的一个条目的 sizeof 将是 8 个字节。即 sizeof(A[0][0]) 将是 8。从起始地址开始计算。

标签: c multidimensional-array memory-address


【解决方案1】:

C 是 row-major ordered,这意味着首先计算最左边的索引。因此:

&A[3] == 1000 + (3 * 10 * sizeof(your_struct))

要找到该列,我们只需添加剩余的索引:

&A[3][7] == 1000 + (3 * 10 * sizeof(your_struct)) + (7 * sizeof(your_struct))

请注意,这与大端与小端架构无关。这只是一个单词中字节的位置,而您想要的是数组中结构的位置。

此外,sizeof(your_struct) 不能保证是 sizeof(n) + sizeof(c),因为编译器可能会填充您的结构。

最后,您的机器的 32 位 特性意味着内存地址寄存器的大小是 32 位。 (或者换句话说,sizeof(void*)==32)。它表明您的处理器实际上可以分配地址到多少内存。这是与 C 中数据类型的大小不同的问题。

【讨论】:

  • 谢谢,这很有帮助!
【解决方案2】:

这不取决于 C 语言标准,而是取决于您正在使用/定位的编译器、编译器版本和操作系统。

获得特定案例结果的唯一方法是手动测试。

【讨论】:

    【解决方案3】:

    这肯定取决于编译器和系统。但无需猜测。您可以简单地编译并尝试

    #include <stdio.h>
    
    int main()
    {
        struct {
            int n;
            char c;
        } A[10][10];
    
        printf("%08x\n", &A[0][0]);
        printf("%08x\n", &A[0][1]);
        printf("%08x\n", &A[1][0]);
        ...
        printf("%08x\n", &A[3][7]);
    
        ...
    }
    

    【讨论】:

      【解决方案4】:

      数组表示法只是计算元素地址并取消引用它的简写,如下所示:

      int a[5][15];
      Address of a[3][7]: &a + 3 * 15 * sizeof(int) + 7 * sizeof(int)
      

      这就是为什么你不能在不知道除最后一个维度之外的所有维度的情况下使用 n 维数组 - 编译器不知道要添加什么偏移量来计算地址。

      在这种情况下,由于您使用的是结构,事情变得复杂了。存在对齐问题,编译器填充结构以对齐字边界。在这种情况下,由于结构本身占用 5 个字节,而下一个字边界将是 8 个字节,因此编译器可能会在结构中添加 3 个未使用的字节以弥补差异。 (这样做有性能优势。)当然,这根本无法保证,您可以手动指定编译器应如何处理此类情况。

      注意:正如其他人所说,这非常依赖于系统和编译器,所以不要把这些当成福音 - 自己尝试一下以绝对确定结果会是什么在你的情况下。

      【讨论】:

      • 你是对的,当然——出于某种原因,我在想专栏专业。谢谢,我马上更新。
      【解决方案5】:

      它完全依赖于系统而不是语言。

      另外所有的2-D、3-D等数组实际上都是按顺序分配的,因为内存是顺序的(0X00000000 to 0xFFFFFFFF)没有这样的2-D内存左右。

      无论是rowmajor还是columnmajor,如何分配内存完全取决于系统

      主行公式:

      &A[3][7] == &A[0][0] + (3 * 10 * sizeof(struct s)) + (7 * sizeof(struct s))
      

      对于主要栏目:

      &A[3][7] == &A[0][0] + (7 * 10 * sizeof(struct s)) + (3 * sizeof(struct s))
      

      编译器还通过结构填充对其进行优化,以加快 CPU 的访问速度。

      所以对于一个结构大小的对象来说,8 而不是5(如果 int 的大小为 4 个字节)

      【讨论】:

        猜你喜欢
        • 2016-03-12
        • 1970-01-01
        • 2012-11-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-02-03
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多