我正在尝试学习如何在C语言中找出地址。对于下面的代码,假设它在一个32位小端机器上编译。
struct {
int n;
char c;
} A[10][10];
假设A[0][0]的地址为1000(十进制),那么A[3][7]的地址是多少呢?感谢您的帮助!
我正在尝试学习如何在C语言中找出地址。对于下面的代码,假设它在一个32位小端机器上编译。
struct {
int n;
char c;
} A[10][10];
假设A[0][0]的地址为1000(十进制),那么A[3][7]的地址是多少呢?感谢您的帮助!
C语言是按行主序排列的,这意味着最左边的索引首先计算。因此:
&A[3] == 1000 + (3 * 10 * sizeof(your_struct))
要找到这一列,我们只需将剩余的索引相加:
&A[3][7] == 1000 + (3 * 10 * sizeof(your_struct)) + (7 * sizeof(your_struct))
这不仅取决于C语言标准,还取决于编译器、编译器版本和您使用/定位的操作系统。
获取您特定情况的结果的唯一方法是手动测试。
数组表示法只是一种简写方式,用于计算元素的地址并对其进行取消引用,如下所示:
int a[5][15];
Address of a[3][7]: &a + 3 * 15 * sizeof(int) + 7 * sizeof(int)
这就是为什么在不知道除了最后一个维度之外的所有维度的情况下不能使用n维数组 - 编译器将不知道要添加什么偏移量才能计算地址。
在这种情况下,由于您正在使用结构体,问题变得更加复杂。存在对齐问题,编译器会填充结构体以对齐到字边界。在这种情况下,由于结构体本身占用5个字节,而下一个字边界将在8个字节处,编译器很可能会向结构体添加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]);
...
}
它完全依赖于系统而不是语言。
此外,所有的2-D、3-D等数组实际上都是按顺序分配的,因为内存是顺序的(0X00000000到0xFFFFFFFF)
没有这样的2-D内存等。
它完全依赖于系统如何分配内存,无论是按行主还是按列主。
行主公式:
&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]
... - leppieoffsetof
、__alignof__
和sizeof
与GCC。 - Basile Starynkevitch