3
int main()
{

    struct a
    {
        struct a *next;
        struct a *prev;
    };

    struct a *A[2];

    printf("Address of (&(A[0])->next) = %p",(&(A[0])->next));
    getch();
    return 0;
}

在上面的 printf 语句中,我正在访问“struct a”结构的“next”指针,当我在开发编译器中运行程序时,它给了我有效的内存地址(尽管我还没有为它分配任何内存)。解释这是如何发生的将非常有帮助。

是否为“下一个”和“上一个”字段分配了内存?

4

2 回答 2

9

让我们想想这意味着什么:

&(A[0])->next

它是next指针的地址(不是它指向的位置,而是指针本身的地址)。并且next指针是 的第一个元素struct a,所以 的地址next与其封闭的地址相同a

因此,表达式是 所struct a引用的地址A[0]。在您的原始代码中,您从不在那里分配任何东西,所以它只是一个正在打印的垃圾值。正如@alk 在另一个答案中指出的那样,您可以初始化变量中的两个指针,A然后您会看到这些值中的第一个正在打印(例如,0x0)。

顺便说一句,如果您想快速初始化A,请这样做,而不是更冗长memset()

struct a *A[2] = {0};

它做同样的事情(将两个指针设置为 0)。

虽然打印的值是垃圾,但代码可能不是非法的。这可能看起来令人惊讶,但请参见此处:取消引用无效指针,然后获取结果的地址- 你得到了类似的东西,尽管不可否认,你已经通过取消引用结构的成员而不是简单地更进一步使用*. 所以我心中的悬而未决的问题是:鉴于指针&*foo何时foo是合法的(如上面的链接所示),同样适用于&foo->bar吗?

于 2013-06-05T11:44:13.417 回答
4
&(A[0])->next

是数组next中第一个结构的成员的地址。A

这可以被认为是&A[0] + offsetof(struct a, next)。即,这只会导致未初始化指针的值A[0]加上next成员与结构基地址的偏移量(恰好为零,因为next它是结构的第一个元素)。

根据 C 标准,您的程序调用未定义的行为,因为它对无效指针执行指针运算。但是,在实践中,这很可能不会崩溃并打印虚假地址(仅执行加法,没有任何内容访问指针后面的内存)。但是,如果您实际上取消引用该指针,则预计会发生崩溃。

于 2013-06-05T11:50:39.080 回答