printf语句有效吗?

时间:2013-06-05 11:32:57

标签: c pointers struct

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”指针。当我在dev编译器中运行程序时,它给了我有效的内存地址(虽然我还没有为它分配任何内存)。对如何发生这种情况的解释将非常有用。

是否为“下一个”&分配了任何内存。 “prev”字段?

2 个答案:

答案 0 :(得分: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)。

虽然打印的值是垃圾,但代码可能并非违法。这可能看起来很令人惊讶,但请看这里:Dereferencing an invalid pointer, then taking the address of the result - 你有类似的东西,但不可否认你通过解除引用结构的一个成员而不是简单地使用*更进一步。因此,我心中的开放性问题是:假设&*foo是指针foo总是合法的(如上面的链接所示),&foo->bar是否也适用?< / p>

答案 1 :(得分:4)

&(A[0])->next

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

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

根据C标准,您的程序会调用未定义的行为,因为它会对无效指针执行指针运算。 然而,实际上,这很可能不会崩溃并打印出虚假地址(只执行添加,没有任何内容访问指针后面的内存)。如果您实际取消引用指针,则会出现崩溃。