Vah*_*yab 0 c struct pointers linked-list
这是我用来学习指向结构体工作方式的代码。正如你在下面看到的,变量的值s不等于它指向的结构体的地址(&amity),奇怪的 *s是等于它。
我还有一些问题:
为什么所有结构实例(甚至&instance.name)的地址都相同?
虽然s和i和j相同,但为什么 的值*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)
打开编译器中的警告,注意它们并修复它们。对于 GCC,从-Wall. 使用 Clang,从 开始-Wmost。使用 Microsoft Visual C++ (MSVC),从/W4. 还将警告升级为错误。对于 GCC 或 Clang,请使用-Werror. 借助 MSVC,使用/WX.
\n\n为什么所有结构体实例的地址(甚至&instance.name)都是相同的?
\n
他们不是。在您的printf调用中,您传递了与转换说明符不匹配的类型的参数。这实际上破坏了所操作的数据printf,因此它的输出不会显示参数的实际值。例如,在:
printf("amity: %s\\t &amity: %p\\t &amity.name:%p \\n", amity, &amity, &amity.name);\nRun Code Online (Sandbox Code Playgroud)\nthe%s需要一个char *参数,但相应的参数是一个结构。在您的 C 实现中,结构可能是通过将其字节复制到堆栈来传递的。这导致指针amity.name位于%s期望找到指针的位置,因此printf\xe2\x80\x9cworked\xe2\x80\x9d 通过使用该指针来打印字符串。但是,then%p需要一个指针,但在第一个指针 for 之后堆栈上的内容%s是结构的更多字节,而不是&amity参数。因为该结构是在堆栈上传递的,所以它占用空间,并且&amity参数稍后出现。因此printf,当寻找 的指针时%p,没有找到&amity参数;它从结构的后面找到一些字节,并将它们转换为指针。
因此,您的输出已损坏,并且不会显示&amity或的值&amity.name。
\n\n虽然 s 和 i 和 j 相同,但为什么 *j 的值与 *s 和 *i 不同?
\n
在 中printf("*s: %p\\t *i: %p\\t *j:%p\\n\\n", *s, *i, *j);,您再次传递结构(*s、*i、 和*j都是结构),其中printf。输出已损坏。
一旦您修复了printf调用以使参数类型与转换说明符匹配,您将看到正确的地址。
\n\n最后,为什么结构体的值仅等于其第一个字段的值?
\n
结构体的值不等于其第一个字段的值。由于输出损坏,您从问题中显示的测试程序中得到的任何印象都是不正确的。
\n但是,结构的地址确实等于第一个字段的地址,因为第一个字段从结构的开头开始,这当然也是结构的开始位置。
\n