tags:

views:

94

answers:

2

Hello,

gcc 4.4.4 c89

Pointers are not the same as arrays. But arrays can decay into pointers.

I was just using memset which first parameter is a pointer. I would like to initialize my structure array.

i.e.

struct devices
{
    char name[STRING_SIZE];
    size_t profile;
    char catagory;
};

struct devices dev[NUM_DEVICES];

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

dev == &dev[0]

But should I pass the first parameter has this:

 memset(&dev, 0, (size_t)NUM_DEVICES * sizeof(*dev));

Many thanks for any advice,

+1  A: 

Edit: Misinterpreted and/or overlooked a part of your code. What you have should work fine, as per @caf's answer.

eldarerathis
Oh, good catch; I didn't even look at the rest of the line
Michael Mrozek
Heh, I had to test to make sure. I didn't see it at first glance, either.
eldarerathis
Hello, I have just tested that myself. STRING_SIZE is 31 bytes.printf("sizeof(*dev) [ %d ]\n", sizeof(*dev));printf("sizeof(dev) [ %d ]\n", sizeof(dev));sizeof(*dev) [ 40 ]sizeof(dev) [ 320 ]Was the output. I think forty sounds about right. Thanks.
robUK
Sorry, but this is wrong. `sizeof(*dev)` is correct - `dev` decays into a pointer to the first element of the array, and `*dev` dereferences that - so `sizeof(*dev)` is the same as `sizeof(dev[0])` and hence is the size of one element of the array.
caf
@caf: I don't think I quite understand that. Wouldn't passing `sizeof(*dev)` to `memset` then only set the first block (element) in the array rather than the entire thing? That seems to be what happens when I test this on my machine.
eldarerathis
Sure, but the OP has multiplied by `NUM_DEVICES`, which is the number of elements in the array. So `sizeof(*dev)` is the size of one element, and `NUM_DEVICES * sizeof(*dev)` is the size of the whole array.
caf
What about `memset(dev, 0, sizeof(devices) * NUM_DEVICES);`?
Duracell
@Duracell: you meant `sizeof(struct devices) * NUM_DEVICES`? That's fine too.
jweyrich
@caf: Oh wow, I overlooked that completely somehow. Then is there any benefit to using `NUM_DEVICES * sizeof(*dev)` instead of just `sizeof(dev)`?
eldarerathis
@Duracell: In C you would need to use `sizeof(struct devices)` - but that would work. However, `NUM_DEVICES * sizeof dev[0]` is the preferred idiom, because that way it will remain correct if you change the type of `dev`.
caf
@eldarerathis: In this case, no - but if `dev` were a pointer rather than an array, then the full multiplication would have to be used (obviously).
caf
+4  A: 

What you have:

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

is fine - you pass a pointer to the first element of the array, and the size of the array. However, the (size_t) cast is unnecessary (sizeof has type size_t, so it will cause the correct promotion) and I find that dev[0] is clearer than *dev in this case:

memset(dev, 0, NUM_DEVICES * sizeof dev[0]);

Alternatively, you can use &dev as the address. In this case, it is probably clearer to use sizeof dev - the size of the whole array:

memset(&dev, 0, sizeof dev);

I say that this is clearer, because it's generally best to have the first parameter be a pointer to the type that's the subject of sizeof in the last parameter: the memset() should look like one of these forms:

memset(p, ..., N * sizeof p[0])
memset(&x, ..., sizeof x)

Note however that this last one only works if dev really is an array - like it is in this case. If instead you have a pointer to the first element of the array, you'll need to use the first version.

caf
+1 for the latter suggestion :-)
jweyrich