I once heard that use of 'sizeof' operator is frowned upon by the
followers of defensive programming.
I once heard that if you looked at the full Moon over
your left shoulder you would be struck dead on the spot.
I understand that it's not safe to
rely on. for example, 'sizeof(short)' or similar, because these values
may differ on different platforms.
Can't resist: "This is obviously some strange usage of the
word 'safe' that I wasn't previously aware of."
Seriously: One *advantage* of sizeof(short) is that it
reports the number of bytes in the implementation's version of
`short', no matter what that number might be. You cannot
"safely" write `2' lest your code find itself running on a
platform with a different-sized `short', and the `2' would be
wrong. If you write `sizeof(short)', on the other hand, you
will always get the right answer -- the answer may be different
on different platforms, but you'll get the value that's right
for the platform at hand.
Another advantage shows up when you deal with types that
are more intricate than `short' or `double' or whatever. In
`struct foo {int a; char *b; double c; short d[MAX]; }', for
example, how many bytes does a `struct foo' instance occupy?
`sizeof(struct foo)' is always right -- hence "safe" -- while
`(4+4+8+2*MAX+2+7)/8*8' is at best a guess, with lots of
opportunity for error.
But are there other reasons stopping
from using sizeof in everyday's code?
C has three sizeof-related traps I'm aware of. Two require
vigilance, and the other can be avoided with simple discipline.
The first is that a function parameter declared as an array
is not actually an array, but a pointer to the array's element
type. In `size_t bar(char array[42]) { return sizeof array; }'
might expect the function to return 42, the number of bytes in a
42-char array. What it actually returns, though, is the number of
bytes in a char*, a pointer to the element type; this is usually
4 or 8 (but *could* be almost anything, even 42).
The second is that until fairly recently `sizeof' never
evaluated its argument. But the C99 Standard introduced the
"variable-length array," an array whose size is given by a non-
constant run-time expression. If you apply `sizeof' to such an
array, it *does* evaluate, at least enough to figure out the
value of the size-controlling expression. And if that expression
has side-effects, re-evaluating it may be problematic.
The third is that the compiler doesn't always know that a
size is being used inappropriately. You might try to allocate
a `struct foo' instance (see above) with
struct foo *ptr;
...
ptr = malloc(sizeof(struct gizmo));
.... having written the wrong type (and size) on the right-hand
side. The compiler will seldom detect this misuse. Hence, the
recommended discipline (relying on non-evaluation):
ptr = malloc(sizeof *ptr);
.... and all's well again.