Hacker News new | ask | show | jobs
by masklinn 4037 days ago
And you really shouldn't use it with a type if you can avoid it anyway, it makes code brittle e.g.

    int *foo;
    // code
    foo = malloc(sizeof(int));
a few months later, change foo to be a double. Code still compiles, no warning, but you're allocating half the memory you need.
2 comments

This is a really great example why you SHOULDN'T think of sizeof as a function. If sizeof were a function, the code

  int *foo = NULL;
  foo = malloc(sizeof(*foo));
would be undefined behavior (dereferencing NULL)!
Dereferencing a null pointer is legal in C. It's the conversion of a null pointer from from an r-value to an l-value that's illegal, which does not happen in that snippet of code.

That's why it's perfectly legal in C to do this (&*foo), even if foo is a null pointer.

> Dereferencing a null pointer is legal in C. It's the conversion of a null pointer from from an r-value to an l-value that's illegal, which does not happen in that snippet of code.

And it does not happen in that snippet of code because sizeof is nothing like a function.

Which is why it's nice to lift stuff out into typedefs. It centralizes them (DRY principle) and avoids this issue.

    typedef int thing_t;
    ...
    thing_t *foo;
    // code
    foo = malloc(sizeof(thing_t));
Why is that better than just getting `sizeof(* foo)`? Even with typedef, I can see this happening in the future:

    typedef int thing_t;
    ...
    thing_t *foo_internal;
    thing_wrapper_t *foo;
    // code
    foo = malloc(sizeof(thing_t));
If you do:

    foo = malloc(sizeof(*foo));
That's at least always on the same line.
That just makes it more verbose.

This, on the other hand, always allocates one object of foo's pointed-to-size, whatever its type:

    foo = malloc(sizeof(*foo));
As an aside, I think nearly any time you want a typedef, it's worth wrapping it in a struct.

    typedef struct { int value; } thing_t;
That way the compiler catches it when you try to pass the wrong thing (at least, more of the time).
DRY is good, but making the structure of your code reflect the actual semantics you want is better. What you want is to allocate space for foo. So write that.
Well, in this (simple) case you can just do

    int *foo;
    foo = malloc(sizeof(*foo));
And avoid the brittleness mentioned.