我正在努力理解指向结构的指针,所以我写了一些包含一些打印语句的示例代码。
struct Student {
uint32_t id;
uint8_t marks[8];
int32_t credit;
};
struct Student jacob;
struct Student *adam = &jacob;
struct Student mary = *adam;
mary.marks[3] = 80;
jacob.marks[3] = 75;
adam->marks[3] = 67;
printf("jacob: %d\n", jacob);
printf("&jacob: %d\n", &jacob);
printf("adam: %d\n", adam);
printf("*adam: %d\n", *adam);
printf("mary: %d\n", mary);
printf("mary.marks[3]: %d\n", mary.marks[3]);
输出结果为:
jacob: 4195856
&jacob: -436012784
adam: -436012784
*adam: 4195856
mary: 4195856
mary.marks[3]: 80
为什么mary.marks[3]
80的值是多少?据我所知,mary
间接指向struct jacob
,因为adam
指向jacob
的地址。因此,adam->marks[3] = 67
行会更改mary.marks[3]
的值,因为它们指向同一位置。
有人可以帮助我理解为什么mary.marks[3]
的价值保持不变吗?
答案 0 :(得分:2)
简而言之,语句struct Student jacob;
为学生结构的一个副本创建空间(无论是在堆栈上还是在内存中,取决于,但对答案并不重要)。
声明struct Student *adam = &jacob;
使adam成为jacob的指针。
声明struct Student mary = *adam;
将未初始化的数据从adam指向的(jacob)复制到为mary分配的新空间。
了解雅各布和玛丽分配空间非常重要。亚当是雅各布的指针。但是当你说mary.marks [3] = 80时,你就会在这个东西中加上一个价值" mary"而事情" jacob"没有改变。
然后您写信至jacob.marks[3]
,然后使用adam->marks[3]
覆盖该内容。
当你打印某个地址时,你应该使用%p。当你用%d打印一个结构时,C只是笨拙地看着内存"好像"它是一个整数。在您说struct Student mary = *adam;
的行中,您正在将包含jacob的(尚未初始化的)内存复制到新分配的mary内存中。这就是printf是相同的原因。如果你打印出来,你会发现它与jacob或adam的内存不同。
答案 1 :(得分:2)
声明
struct Student *adam = &jacob;
将调用未定义的行为,因为jacob
仅被声明,并且它的成员未初始化。
对printf
中的数据类型使用错误的说明符也会导致程序的未定义行为。您还应该注意,struct不能传递给printf
。
现在改变你的代码
struct Student {
uint32_t id;
uint8_t marks[3];
int32_t credit;
};
int main(void)
{
struct Student jacob = {0,{0},0};
struct Student *adam = &jacob;
struct Student mary = *adam;
mary.marks[3] = 80;
jacob.marks[3] = 75;
adam->marks[3] = 67;
printf("mary.marks[3]: %d\n", mary.marks[3]);
}
现在初始化jacob
,初始化struct Student
指针,其值是合法的。现在,adam
指向jacob
,mary
使用 jacob
副本进行初始化(对jacob
成员的任何更改将不会在mary
)中看到
在printf
中,您正在打印mary.marks[3]
,其值为80
。这些陈述
jacob.marks[3] = 75;
adam->marks[3] = 67;
对mary
无效。打印jacob.marks[3]
或adam->marks[3]
,您会看到更改。
答案 2 :(得分:1)
由于mary
不是指针,因此当您将*adam
分配给mary
时,您刚刚复制了adam
指向的值,那么mary
持有不是adam
所指出的;这就是为什么尝试更改*adam
的值并不会对mary
的值进行任何更改。
答案 3 :(得分:1)
您有两个类型为student
的结构变量和一个类型为student
的结构指针。
a)
jacob
未初始化且指针*adam
指向jacob。b)然后您通过指针引用
jacob
将mary
复制到adam
。c)
jacob
和mary
是两个不同的地址;每个都有自己的副本 数据。d)修改
mary.mary[3]
后,只会在mary
更新 不在jacob
。
mary.marks[3] = 80;
是最后更新的值,因此将打印。
jacob.marks[3] = 75; //direct
adam->marks[3] = 67; //via pointer to the same variable
两者都更新到同一位置。你正在覆盖:
jacob.marks[3]
另请遵循评论中的建议。