我正在尝试学习如何在C中找出地址。对于下面的代码,假设它是在32位小端机器上编译的。
struct {
int n;
char c;
} A[10][10];
假设A [0] [0]的地址是1000(十进制),A [3] [7]的地址是什么?任何帮助表示赞赏!
答案 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个字节)