Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/60.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
用C语言计算地址_C_Multidimensional Array_Memory Address - Fatal编程技术网

用C语言计算地址

用C语言计算地址,c,multidimensional-array,memory-address,C,Multidimensional Array,Memory Address,我正在尝试学习如何用C语言计算地址。对于下面的代码,假设它是在一台32位的little endian机器上编译的 struct { int n; char c; } A[10][10]; 假设[0][0]的地址是1000(十进制),那么[3][7]的地址是什么?感谢您的帮助 这并不取决于C语言标准,而是取决于编译器、编译器版本和您正在使用的操作系统/目标 获取特定情况的结果的唯一方法是手动测试。数组表示法只是计算元素地址并取消对其引用的简写,如下所示: int a[5][15]

我正在尝试学习如何用C语言计算地址。对于下面的代码,假设它是在一台32位的little endian机器上编译的

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

假设[0][0]的地址是1000(十进制),那么[3][7]的地址是什么?感谢您的帮助

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


获取特定情况的结果的唯一方法是手动测试。

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

int a[5][15];
Address of a[3][7]: &a + 3 * 15 * sizeof(int) + 7 * sizeof(int)
这就是为什么在不知道最后一个维度的情况下不能使用n维数组的原因——为了计算地址,编译器不知道向它添加什么偏移量

在这种情况下,由于您使用的是结构,所以问题变得复杂。存在对齐问题,编译器填充结构以对齐单词边界。在这种情况下,由于结构本身需要5个字节,下一个单词边界将是8个字节,因此编译器可能会向结构添加3个未使用的字节以弥补差异。当然,这根本不能保证,您可以手动指定编译器应该如何处理这种情况

注意:正如其他人所说,这非常依赖于系统和编译器,因此不要将任何一个作为福音-自己尝试一下,以绝对确定在您的情况下会得到什么结果。

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

&A[3] == 1000 + (3 * 10 * sizeof(your_struct))
要查找该列,只需添加剩余的索引:

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

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

另外,
sizeof(您的_结构)
也不能保证是
sizeof(n)+sizeof(c)
,因为编译器可以填充您的结构


最后,机器的32位特性意味着内存地址寄存器的大小为32位。(或者换句话说,
sizeof(void*)==32
)。它指示处理器实际可以为地址分配多少内存。这与C语言中数据类型的大小是一个独立的问题。

这当然取决于编译器和系统。但没必要猜测。您可以简单地编译并尝试

#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]);

    ...
}
#包括
int main()
{
结构{
int n;
字符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]);
...
}

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

此外,所有二维、三维等数组实际上都是按顺序分配的,因为内存是按顺序分配的
(0X00000000到0xffffff)
没有这样的二维内存

无论是
主内存还是
主内存,其分配方式完全取决于系统

row major的公式为:

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

您的意思肯定是
&A[0][0]
。您应该在实际程序中尝试。详细信息是特定于编译器、操作系统、ABI和指令集的。您可能需要使用GCC使用
offsetof
alignof
sizeof
。为什么不编译它,打印地址,然后弄清楚编译器是如何安排的?这可以让您理解,我希望最有可能的是,结构将被填充到所使用的最大数据类型的最近类型边界。这里是int,所以A的一个条目的sizeof是8字节。i、 e.sizeof(A[0][0])将为8。从起始地址开始计算。谢谢,这非常有用!当然,你是对的——出于某种原因,我在想专栏专业。谢谢,我现在就更新。