3

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

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

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

4

5 回答 5

8

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 中数据类型的大小不同的问题。

于 2012-11-12T06:10:29.033 回答
2

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

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

于 2012-11-12T06:09:24.870 回答
1

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

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

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

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

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

于 2012-11-12T06:09:31.697 回答
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]);

    ...
}
于 2012-11-12T06:17:01.997 回答
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 个字节)

于 2012-11-12T06:20:16.647 回答