在C中找出地址

时间:2012-11-12 06:04:20

标签: c multidimensional-array memory-address

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

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

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

5 个答案:

答案 0 :(得分:8)

C是行主要排序,这意味着首先计算最左侧的索引。因此:

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

要查找列,我们只需添加剩余索引:

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

请注意,这与big-endian vs little-endian架构无关。这只是一个单词中字节的位置,而你想要一个数组中结构的位置。

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

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

答案 1 :(得分:2)

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

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

答案 2 :(得分:1)

数组表示法只是计算元素地址和解除引用的简写,如下所示:

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

这就是为什么你不能使用n维数组而不知道除了最后一个维度之外的所有维度 - 编译器不知道要添加到哪个偏移量,以便计算地址。

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

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

答案 3 :(得分:1)

这肯定是编译器和系统相关的。但没必要猜。你可以简单地编译并尝试

#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 :(得分:0)

完全取决于系统,而不是语言。

所有2-D,3-D等阵列实际上都是以顺序方式分配的,因为内存是顺序的(0X00000000 to 0xFFFFFFFF),所以没有这样的2-D内存。

完全依赖于系统分配内存的方式,无论是row主要还是column主要

行专业的公式:

&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个字节)