为什么指针值不等于它指向的结构体的地址?

Vah*_*yab 0 c struct pointers linked-list

这是我用来学习指向结构体工作方式的代码。正如你在下面看到的,变量的值s不等于它指向的结构体的地址(&amity),奇怪的 *s是等于它。

我还有一些问题:

为什么所有结构实例(甚至&instance.name)的地址都相同?

虽然sij相同,但为什么 的值*j*s*i

最后,为什么结构体的值仅等于其第一个字段的值?

该代码是从《Head First C》一书中修改而来的。

#include <stdio.h>

typedef struct island {
    char *name;
    char *open;
    char *close;
    struct island *next;
} island;

void text(island *s);

int main(void) {

    island amity = { "Amity", "09:00", "17:00", NULL };
    island craggy = { "Craggy", "09:00", "17:00", NULL };
    island isla_nublar = { "Isla Nublar", "09:00", "17:00", NULL };
    island shutter = { "Shutter", "09:00", "17:00", NULL };

    amity.next = &craggy;
    craggy.next = &isla_nublar;
    isla_nublar.next = &shutter;

    printf("amity: %s\t  &amity: %p\t &amity.name:%p \n", amity, &amity, &amity.name);
    printf("craggy: %s\t  &craggy: %p\t &craggy.name:%p \n", craggy, &craggy, &craggy.name);
    printf("shutter: %s  &shutter: %p\t &shutter.name:%p \n\n", shutter, &shutter, &shutter.name);

    text(&amity);
}

void text(island *s) {
    island *i = s;
    island *j = i;

    printf("s: %p\t  i: %p\t  j:%p\n", s, i, j);
    printf("&s: %p\t &i: %p\t &j:%p\n", &s, &i, &j);
    printf("*s: %p\t *i: %p\t *j:%p\n\n", *s, *i, *j);

    for (; i != NULL; i = i->next) {
        printf("Name: %s open: %s-%s\n", i->name, i->open, i->close);
    }
}
Run Code Online (Sandbox Code Playgroud)

这是结果:

#include <stdio.h>

typedef struct island {
    char *name;
    char *open;
    char *close;
    struct island *next;
} island;

void text(island *s);

int main(void) {

    island amity = { "Amity", "09:00", "17:00", NULL };
    island craggy = { "Craggy", "09:00", "17:00", NULL };
    island isla_nublar = { "Isla Nublar", "09:00", "17:00", NULL };
    island shutter = { "Shutter", "09:00", "17:00", NULL };

    amity.next = &craggy;
    craggy.next = &isla_nublar;
    isla_nublar.next = &shutter;

    printf("amity: %s\t  &amity: %p\t &amity.name:%p \n", amity, &amity, &amity.name);
    printf("craggy: %s\t  &craggy: %p\t &craggy.name:%p \n", craggy, &craggy, &craggy.name);
    printf("shutter: %s  &shutter: %p\t &shutter.name:%p \n\n", shutter, &shutter, &shutter.name);

    text(&amity);
}

void text(island *s) {
    island *i = s;
    island *j = i;

    printf("s: %p\t  i: %p\t  j:%p\n", s, i, j);
    printf("&s: %p\t &i: %p\t &j:%p\n", &s, &i, &j);
    printf("*s: %p\t *i: %p\t *j:%p\n\n", *s, *i, *j);

    for (; i != NULL; i = i->next) {
        printf("Name: %s open: %s-%s\n", i->name, i->open, i->close);
    }
}
Run Code Online (Sandbox Code Playgroud)

Eri*_*hil 5

打开编译器中的警告,注意它们并修复它们。对于 GCC,从-Wall. 使用 Clang,从 开始-Wmost。使用 Microsoft Visual C++ (MSVC),从/W4. 还将警告升级为错误。对于 GCC 或 Clang,请使用-Werror. 借助 MSVC,使用/WX.

\n
\n

为什么所有结构体实例的地址(甚至&instance.name)都是相同的?

\n
\n

他们不是。在您的printf调用中,您传递了与转换说明符不匹配的类型的参数。这实际上破坏了所操作的数据printf,因此它的输出不会显示参数的实际值。例如,在:

\n
printf("amity: %s\\t  &amity: %p\\t &amity.name:%p \\n", amity, &amity, &amity.name);\n
Run Code Online (Sandbox Code Playgroud)\n

the%s需要一个char *参数,但相应的参数是一个结构。在您的 C 实现中,结构可能是通过将其字节复制到堆栈来传递的。这导致指针amity.name位于%s期望找到指针的位置,因此printf\xe2\x80\x9cworked\xe2\x80\x9d 通过使用该指针来打印字符串。但是,then%p需要一个指针,但在第一个指针 for 之后堆栈上的内容%s是结构的更多字节,而不是&amity参数。因为该结构是在堆栈上传递的,所以它占用空间,并且&amity参数稍后出现。因此printf,当寻找 的指针时%p,没有找到&amity参数;它从结构的后面找到一些字节,并将它们转换为指针。

\n

因此,您的输出已损坏,并且不会显示&amity或的值&amity.name

\n
\n

虽然 s 和 i 和 j 相同,但为什么 *j 的值与 *s 和 *i 不同?

\n
\n

在 中printf("*s: %p\\t *i: %p\\t *j:%p\\n\\n", *s, *i, *j);,您再次传递结构(*s*i、 和*j都是结构),其中printf。输出已损坏。

\n

一旦您修复了printf调用以使参数类型与转换说明符匹配,您将看到正确的地址。

\n
\n

最后,为什么结构体的值仅等于其第一个字段的值?

\n
\n

结构体的值不等于其第一个字段的值。由于输出损坏,您从问题中显示的测试程序中得到的任何印象都是不正确的。

\n

但是,结构的地址确实等于第一个字段的地址,因为第一个字段从结构的开头开始,这当然也是结构的开始位置。

\n