'sizeof' in defensve programming

M

Mark

I once heard that use of 'sizeof' operator is frowned upon by the followers
of defensive programming. I understand that it's not safe to rely on. for
example, 'sizeof(short)' or similar, because these values may differ on
different platforms. But are there other reasons stopping from using sizeof
in everyday's code?
 
I

Ian Collins

I once heard that use of 'sizeof' operator is frowned upon by the
followers of defensive programming.

From whom?
I understand that it's not safe to
rely on. for example, 'sizeof(short)' or similar, because these values
may differ on different platforms.

Isn't that a reason *too* use sizeof?
But are there other reasons stopping from using sizeof in everyday's code?

No
 
N

Nick Keighley

I once heard that use of 'sizeof' operator is frowned upon by the followers
of defensive programming.

sounds like some sort of cult. Presumably they surround their code
with little pointy sticks.

I understand that it's not safe to rely on.

it reliably evaluates to the size of its argument. In what way is this
unreliable?
for
example, 'sizeof(short)' or similar, because these values may differ on
different platforms.

sizeof(short) may yeild different values on different platforms. In
what way would it be better to use a fixed but incorrect value?

But are there other reasons stopping from using sizeof
in everyday's code?

I haven't heard a reason not to use it non-everyday code (feast day
code?) yet
 
M

Malcolm McLean

I once heard that use of 'sizeof' operator is frowned upon by the followers
of defensive programming. I understand that it's not safe to rely on. for
example, 'sizeof(short)' or similar, because these values may differ on
different platforms. But are there other reasons stopping from using sizeof
in everyday's code?
You've got the wrong end of the stick.

printf("%d\n", (int) sizeof(short) );

will usually print out the digit '2'. Occasionally you will get a '1'
or a '4', and other numbers are theoreticaly possible.
Just occasionally a difference like this will break programs.

However if you want an array of, say, 20 shorts in dynamic memory

ptr = malloc(20 * sizeof(short));

will get you a memory buffer of the right size. You don't care whether
it is 20 bytes, 40 bytes or 80 bytes. All you care is that it can hold
20 shorts. You might say "I want a 16-bit integer, not a short".
Generally, you don't. If short isn't 16 bits, then there will be a
good reason for it, eg the computer has oceans of memory, and 32 bit
reads are faster than 16 bit reads.
 
E

Eric Sosman

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.
 
R

Richard Bos

Mark said:
I once heard that use of 'sizeof' operator is frowned upon by the followers
of defensive programming.

You heard wrong.
I understand that it's not safe to rely on. for example, 'sizeof(short)' or
similar, because these values may differ on different platforms.

This is exactly why you use sizeof (short), rather than a hard-coded 3.

Even better is not using sizeof (<some-type>), but sizeof <object> -
which in most practical cases boils down to sizeof *<pointer>. For
example, in

some_type *pointer1, *pointer2;

pointer1 = malloc(AMOUNT * sizeof (some_type));
pointer2 = malloc(AMOUNT * sizeof *pointer2);

both lines (try to!) allocate memory for AMOUNT objects of some_type,
but if I change the first line to

some_better_type *pointer1, *pointer2;

(for example, if I notice that my linked list is getting too slow, and I
want to change to using a balanced tree), the allocation of pointer1 is
now wrong, while that of pointer2 remains correct. Hence, using sizeof
<object> or usually sizeof *<pointer> is more sturdy and easily
maintainable than using sizeof (<type>) directly.

Richard
 
K

Keith Thompson

Eric Sosman said:
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.
[...]

I don't think that's an actual problem.

Consider:

int len = 42;
double vla[len];
len ++;

The length of the VLA is determined when it's created, and the length
expression is magically stored somewhere. Changing the value of len
doesn't change the length of the array, and computing ``sizeof vla''
doesn't re-compute the expression that determined its size; it just
retrieves the stored value. If you have:

double vla[func()];

computing ``sizeof vla'' doesn't call func() again.

The C99 standard says that the argument to sizeof is evaluated if it's
a variable-length array. I can't think of a case where this actually
matters.
 
E

Eric Sosman

Eric Sosman said:
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.
[...]

I don't think that's an actual problem.

Consider:

int len = 42;
double vla[len];
len ++;

The length of the VLA is determined when it's created, and the length
expression is magically stored somewhere. Changing the value of len
doesn't change the length of the array, and computing ``sizeof vla''
doesn't re-compute the expression that determined its size; it just
retrieves the stored value. If you have:

double vla[func()];

computing ``sizeof vla'' doesn't call func() again.

The C99 standard says that the argument to sizeof is evaluated if it's
a variable-length array. I can't think of a case where this actually
matters.

As a shunner of VLA's I might be wrong about this, but I
think that if you apply sizeof to a VLA type rather than to an
actual array object, it can make a difference:

int len = 42;
size_t s1 = sizeof(double[len++]);
size_t s2 = sizeof(int[len++]);
assert (len == 44);

(Have I tried this? No; I haven't even compiled it.)
 
P

Phil Carmody

Eric Sosman said:
On 4/8/2010 4:16 AM, Mark wrote: ....
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.

I think I'd say the third is sizeof('a') not being sizeof(char).

Phil
 
M

Mark

Hm, I got it all wrong I guess. Thanks for enlightening me, should be more
careful before posting silly question the next time.
 
M

Michael Tsang

Phil said:
Eric Sosman said:
On 4/8/2010 4:16 AM, Mark wrote: ...
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.

I think I'd say the third is sizeof('a') not being sizeof(char).

Phil
I wonder who actually writes practical programs which depends on the value
of sizeof('a').
 
M

Michael Foukarakis

I once heard that use of 'sizeof' operator is frowned upon by the followers
of defensive programming.

Go find the guy who told you that and slap him silly.
I understand that it's not safe to rely on. for
example, 'sizeof(short)' or similar, because these values may differ on
different platforms.

What is not safe is using 'sizeof(short)' as a substitute for 2.
Assumptions will always get you in trouble. sizeof will help you with
that, also.
But are there other reasons stopping from using sizeof
in everyday's code?

No. None. Zero.
 
P

Phil Carmody

Michael Tsang said:
Phil said:
Eric Sosman said:
On 4/8/2010 4:16 AM, Mark wrote: ...
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.

I think I'd say the third is sizeof('a') not being sizeof(char).

I wonder who actually writes practical programs which depends on the value
of sizeof('a').

Have you ever seen a macro which took the sizeof one of its object-
type arguments? The person who writes that macro is independent of
the person who finally invokes sizeof('a').

Phil
 
K

Keith Thompson

Phil Carmody said:
Michael Tsang said:
Phil Carmody wrote: [...]
I wonder who actually writes practical programs which depends on the value
of sizeof('a').

Have you ever seen a macro which took the sizeof one of its object-
type arguments? The person who writes that macro is independent of
the person who finally invokes sizeof('a').

Have you ever seen such a macro invoked with a character constant
as its argument? I'm not saying it never happens, or even that
it's particularly unlikely, but I don't recall ever seeing it myself.

I don't think I've ever seen *any* real (i.e., non-contrived) code
that's broken by the difference in the semantics of sizeof('a')
between C and C++.
 
P

Phil Carmody

Keith Thompson said:
Phil Carmody said:
Michael Tsang said:
Phil Carmody wrote: [...]
I wonder who actually writes practical programs which depends on the value
of sizeof('a').

Have you ever seen a macro which took the sizeof one of its object-
type arguments? The person who writes that macro is independent of
the person who finally invokes sizeof('a').

Have you ever seen such a macro invoked with a character constant
as its argument? I'm not saying it never happens, or even that
it's particularly unlikely, but I don't recall ever seeing it myself.

I like to be protected from the innards of macros, I wouldn't
necesarily recognise such an invocation were I to see one, simply
as I wouldn't tie the use of sizeof with the use of a literal char.
I don't think I've ever seen *any* real (i.e., non-contrived) code
that's broken by the difference in the semantics of sizeof('a')
between C and C++.

I wouldn't find such code entirely unexpected were I to encounter
it though. However, If you look at my recently Morton-accepted
patches, for example, you'd be right to conclude that I'm not
surprised by much any more, there's a lot of messed up C out there.
(I found those using a static code analysis tool called 'grep'.)

Phil
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,069
Latest member
SimplyleanKetoReviews

Latest Threads

Top