What exactly does the C Structure Dot Operator Do (Lower Level Perspective)?

前端 未结 4 2717
南笙
南笙 2021-02-20 16:42

I have a question regarding structs in C. So when you create a struct, you are essentially defining the framework of a block of memory. Thus when you create an instance of a str

4条回答
  •  抹茶落季
    2021-02-20 17:22

    When it works, the "." behavior of the "." operator is equivalent to taking the address of the structure, indexing it by the offset of the member, and converting that to a pointer of the member type, and dereferencing it. The Standard, however, provides that there are situations where that isn't guaranteed to work. For example, given:

    struct s1 {int x,y; }
    struct s2 {int x,y; }
    void test1(struct s1 *p1, struct s2 *p2)
    {
      s1->x++;
      s2->x^=1;
      s1->x--;
      s2->x^=1;
    }
    

    a compiler may decide that there's no legitimate way that p1->x and p2->x can identify the same object, so it may reorder the code so as to the ++ and -- operations on s1->x cancel, and the ^=1 operations on s2->x cancel, thus leaving a function that does nothing.

    Note that the behavior is different when using unions, since given:

    union u { struct s1 v1; struct s2 v2; };
    
    void test2(union u *uv)
    {
      u->v1.x^=1;
      u->v2.x++;
      u->v1.x^=1;
      u->v2.x--;
    }
    

    the common-initial-subsequence rule indicates that since u->v1 and u->v2 start with fields of the same types, an access to such a field in u->v1 is equivalent to an access to the corresponding field in u->v2. Thus, a compiler is not allowed to resequence things. On the other hand, given

    void test1(struct s1 *p1, struct s2 *p2);
    void test3(union u *uv)
    {
      test1(&(u.v1), &(u.v2));
    }
    

    the fact that u.v1 and u.v2 start with matching fields doesn't guard against a compiler's assumption that the pointers won't alias.

    Note that some compilers offer an option to force generation of code where member accesses always behave equivalent to the aforementioned pointer operations. For gcc, the option is -fno-strict-alias. If code will need to access common initial members of varying structure types, omitting that switch may cause one's code to fail in weird, bizarre, and unpredictable ways.

提交回复
热议问题