Struct成员不通过指向struct的指针进行更新

时间:2017-01-29 05:12:10

标签: c pointers struct

我正在努力理解指向结构的指针,所以我写了一些包含一些打印语句的示例代码。

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]的价值保持不变吗?

4 个答案:

答案 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指向jacobmary使用 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)然后您通过指针引用jacobmary复制到adam

     

c)jacobmary是两个不同的地址;每个都有自己的副本   数据。

     

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]

另请遵循评论中的建议。