Why use the address of the first element of the structure, not the structure?

I just found another code base at work, where developers sequentially use the address of the first structs element when copying / comparing / setting, and not in the structure itself. Here is a simple example.

First enter the structure type:

typedef struct { int a; int b; } foo_t; 

Then there is a function that creates a copy of such a structure:

 void bar(foo_t *inp) { foo_t l; ... memcpy(&l.a, &inp->a, sizeof(foo_t)); ... } 

I myself would not write the memcpy call in this way, and I began with the suspicion that the original developers simply did not quite understand the pointers and structures in C. However, now I saw this in two unrelated code bases, without common developers, so I start to doubt myself .

Why use this style?

+59
c struct
Nov 04 '13 at
source share
6 answers

No one should do this. If you are rebuilding structural elements, you have problems.

+61
Nov 04 '13 at 20:44
source share

Instead of this:

 memcpy(&l.a, &inp->a, sizeof(foo_t)); 

You can do it:

 memcpy(&l, inp, sizeof(foo_t)); 

While this can be dangerous and misleading, both statements actually do the same here that C ensures that there is no padding in front of the first element of the structure.

But it’s best to just copy the structure objects using a simple assignment operator:

 l = *inp; 

Why use this style?

My guess is ignorance or bad discipline.

+60
Nov 04 '13 at 20:47
source share

There wouldn’t be. If you ever moved a into a structure or you inserted its elements (s), you introduced a memory error.

+16
Nov 04 '13 at 20:44
source share

This code is unsafe because reordering the elements of a structure can cause memcpy gain access outside the structure if member a is not the first member.

However, it is possible that the members are deliberately ordered within the structure, and the programmer only wants to copy a subset of them, starting from member a and running to the end of the structure. In this case, the code can be made safe with the following change:

  memcpy(&l.a, &inp->a, sizeof(foo_t) - offsetof(foo_t, a)); 

Now members of the structure can be rearranged in any order, and this memcpy will never go beyond.

+11
Nov 05 '13 at 10:19
source share

This is a very bad habit. For example, a structure may have, for example, another member. This is an insanely careless habit, and I am surprised to learn that someone will do it.

Others have already noted this; the one that bothers me is this:
 struct Foo rgFoo [3]; struct Foo *pfoo = &rgFoo [0]; 

instead

 struct Foo *pfoo = rgfoo; 

Why allocate an array by index and then accept the address again? This is already an address, the only difference is that pfoo is technically

 struct Foo *const, 

not

 struct Foo *. 

But I always saw the first one.

+1
Nov 06 '13 at 16:15
source share

In fact, there is one legitimate precedent for this: building a class hierarchy.

When treating structures as instances of a class, the first member (i.e., offset 0) will usually be an instance of a supertype ... if a supertype exists. This allows simple movement to move between using a subtype and a supertype. Very useful.

Regarding Darren Stone, pay attention to the intention, this is expected when doing OO in C.

In any other case, I would suggest avoiding this pattern and accessing the element directly, for the reasons already indicated.

+1
May 28 '15 at 19:22
source share



All Articles