C conventions - how to use memset on array field of structure

I would like to tell you about the correct use of memset when zeroing an array field in a structure (language - C).

Let's say we have the following structure:

  struct my_struct {
        int a[10]
    }

      

Which of the following implementations is more correct?

Option 1:

void f (struct my_struct * ptr) {
    memset(&ptr->a, 0, sizeof(p->a));
}

      

Option 2:

void f (struct my_struct * ptr) {
        memset(ptr->a, 0, sizeof(p->a));
}

      

Notes:

If the field was of a primitive type or another struct (for example, 'int'), option 2 would not work, and if it were parameter 1 (*) of a pointer, it would not work.

Please advise

+3


source to share


2 answers


For a non-composite type, you won't use it at all memset

, because direct assignment will be easier and potentially faster. It would also provide compiler optimization by calling the function.

For arrays, option 2 works because the array is forcibly converted to a pointer for most operations.

For pointers, note that option 2 uses the value of the pointer, not the pointer itself, whereas for an array, a pointer to an array is used.



Option 1 gives the address of the object itself. For a pointer, that is, a pointer (if it "works" depends on your intention), for an array, this is an array, which is always the address of its first element β€” but the type is different here (irrelevant, since it memset

takes void *

and is internally converted to char *

).

So: it depends; for an array, I don't see much of a difference actually, except that the operator-address can confuse reads not familiar with operator-continuity (and that's more for input). As a personal opinion: I prefer the simpler syntax, but I won't complain about the other.

Note that memset

with any other value than 0

, it doesn't make much sense; it may not even guarantee that the array of pointers will be interpreted as a null pointer.

+1


source


IMO option 1 is preferred because the same pattern works for any object, not just arrays:

memset(&obj, 0, sizeof obj);

      



You can simply tell from this statement that it does not cause a buffer overflow - that is, it does not overflow. It is still possible that it does not do what it was intended to do (for example, if obj

is a pointer and it should have indicated what the pointer was pointing to), but at least the damage is contained.

However, if you accidentally use memset(p, 0, sizeof p)

by pointer, you can write past the end of the object being pointed to; or if the object is larger than sizeof p

, you leave the object in a strange state.

+1


source







All Articles