24

gcc 4.4.4 c89

I have the following structure.

struct device_sys
{
    char device[STRING_SIZE];
    int id;
    char category;
};

int main(void)
{
    struct device_sys dev_sys[NUM_DEVICES];

    memset(dev_sys, 0, (size_t)NUM_DEVICES * sizeof(dev_sys));

    return 0; 
}

I get a stack dump when I call memset. Is this not the correct way to initialize an structure array?

1
  • 1
    If you typedef struct device_sys to dev_sys, you can retain the memset you have mentioned. typedef struct device_sys dev_sys; memset(dev_sys, 0, NUM_DEVICES * sizeof(dev_sys)); Commented Aug 28, 2014 at 12:59

4 Answers 4

48

Either

memset(&dev_sys, 0, sizeof dev_sys);

or

memset(dev_sys, 0, NUM_DEVICES * sizeof(struct device_sys));

Or, if you prefer

memset(dev_sys, 0, NUM_DEVICES * sizeof *dev_sys);

but not what you have in your original variant.

Note, that in your specific case in all variants you can use either &dev_sys or dev_sys as the first argument. The effect will be the same. However, &dev_sys is more appropriate in the first variant, since if follows the memset(ptr-to-object, object-size) idiom. In the second and third variants it is more appropriate to use dev_sys (or &dev_sys[0]), since it follows the memset(ptr-to-first-element, number-of-elements * element-size) idiom.

P.S. Of course, instead of using all that hackish memset trickery, in your particular case you should have just declared your array with an initializer

struct device_sys dev_sys[NUM_DEVICES] = { 0 };

No memset necessary.

Sign up to request clarification or add additional context in comments.

13 Comments

OP said c89, isn't that initializer c99?
@bstpierre: No. Why? Aggregate initializers were in C since the beginning of times (well, almost).
for your first example. &dev_sys. Isn't that the (address of). Like the address of the actual pointer. The dev_sys is already at pointer. If I have declared like this struct device *dev_sys. For the first argument I would have just sent the pointer dev_sys. Thanks
@robUK: dev_sys is not a pointer, dev_sys is an array. While it might "pretend" to be a pointer in some contexts, it is not really a pointer. &dev_sys gives you a pointer to the entire array, which is numerically the same as the pointer to its first element (which in turn is why you can use either with the same effect). If you declared it as struct device *dev_sys (a pointer), the &dev_sys wouldn't work. But when it is declared as an actual array (as in your OP), the &dev_sys will work.
@AnT You are right. The example absolutely correct. I've compared your and my code. I have the impression, that your first example compiler-dependant. And in my case I've used too old gcc version.
|
11

There's a typo in your code. Fix:

memset(dev_sys, 0, (size_t)NUM_DEVICES * sizeof(struct device_sys));

Picking good names avoid half the bugs. I'd recommend "devices".

1 Comment

probably even safer way: memset(dev_sys, 0, sizeof(dev_sys));
2

For an array, sizeof gets you the entire size of the array, not the size of an individual element. The sizeof operator is one of the few places where an array is not treated as a pointer to its first element.

Comments

1

You have to pass the sizeof operator the type and not the variable.

memset(dev_sys, 0, (size_t)NUM_DEVICES * sizeof(struct device_sys));

I prefer to use typedef for the struct.

typedef struct tag_device_sys
{
    char device[STRING_SIZE];
    int id;
    char category;
} device_sys;

The you can use memset as follows:

    memset(dev_sys, 0, (size_t)NUM_DEVICES * sizeof(device_sys));

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.