473,883 Members | 1,428 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Pointer dereference rather than sizeof?

I recently read an article containing numerous gripes about common C
practices. One of them contained a gripe about the use of the sizeof
operator as an argument to malloc calls. The supposed "right" way to go
about calling malloc instead is to dereference a pointer; apparently even
if said pointer is undefined.

E.g.
ptr = malloc(sizeof(s truct some_struct)); = wrong

ptr = malloc(*ptr); = right

The method works on my platform, but doesn't really sit right with me. Is
the code portable? Standard? I've been looking myself, but haven't come
across anything forbidding it as of yet.

Aug 25 '08 #1
98 6472
Micheal Smith wrote:
I recently read an article containing numerous gripes about common C
practices. One of them contained a gripe about the use of the sizeof
operator as an argument to malloc calls. The supposed "right" way to go
about calling malloc instead is to dereference a pointer; apparently even
if said pointer is undefined.

E.g.
ptr = malloc(sizeof(s truct some_struct)); = wrong

ptr = malloc(*ptr); = right
I'm sure you misunderstood.

If ptr is declared as
struct some-struct *ptr;
the first method is poor, but the second is an abomination.
It should be
ptr = malloc(sizeof *ptr);

It is not the operator 'sizeof' that is the problem, but the argument to
the operator. Note that sizeof *ptr is a compile-time constant and is
independent of ptr being initialized to some actual storage in the
correct form. In your suppose 'right' form, you are courting severe errors.

Aug 25 '08 #2
On Sun, 24 Aug 2008 23:50:56 -0400, Martin Ambuhl wrote:
Micheal Smith wrote:
>I recently read an article containing numerous gripes about common C
practices. One of them contained a gripe about the use of the sizeof
operator as an argument to malloc calls. The supposed "right" way to
go about calling malloc instead is to dereference a pointer; apparently
even if said pointer is undefined.

E.g.
ptr = malloc(sizeof(s truct some_struct)); = wrong

ptr = malloc(*ptr); = right

I'm sure you misunderstood.

If ptr is declared as
struct some-struct *ptr;
the first method is poor, but the second is an abomination. It should be
ptr = malloc(sizeof *ptr);

It is not the operator 'sizeof' that is the problem, but the argument to
the operator. Note that sizeof *ptr is a compile-time constant and is
independent of ptr being initialized to some actual storage in the
correct form. In your suppose 'right' form, you are courting severe
errors.
Ah, there was a slip in my example. Thanks for the correction. It
definitely is
ptr = malloc(sizeof *ptr);

In case there's some misunderstandin g I'm not touting either to be
right. Actually in my own estimation I'd prefer the "wrong" example.
Aug 25 '08 #3
On Aug 24, 8:59 pm, Micheal Smith <xul...@cheapbs d.netwrote:
[asking about difference between `ptr = malloc(sizeof(s truct some_struct))' and `ptr = malloc(sizeof(* ptr))']
The disadvantage of the first form is that it is up to the programmer
to ensure that the type given in the call to malloc() agrees with the
type in the declaration of ptr. If I inadvertently write

struct other_struct *ptr;

ptr = malloc(sizeof(s truct some_struct));

this code is almost certainly not what I want, but the compiler will
not tell me anything is wrong. On the other hand, if I use the second
form, there is no possibility of a mismatch, and if I later change the
type from 'struct some_struct' to `struct third_struct', I only have
to change it in one place.
Aug 25 '08 #4
Micheal Smith said:
I recently read an article containing numerous gripes about common C
practices. One of them contained a gripe about the use of the sizeof
operator as an argument to malloc calls. The supposed "right" way to go
about calling malloc instead is to dereference a pointer; apparently even
if said pointer is undefined.

E.g.
ptr = malloc(sizeof(s truct some_struct)); = wrong
Well, not wrong, just not very maintainable.
>
ptr = malloc(*ptr); = right
Wrong, wrong, wrong, wrong, wrong. (BUT see below - because you're onto
something good here.)
The method works on my platform,
No, it doesn't, because (if, as you presumably mean to say, the pointer's
value is indeterminate) evaluating the pointer to enable it to be
dereferenced gives you undefined behaviour. (BUT see below - because
you're onto something good here.)
but doesn't really sit right with me. Is
the code portable? Standard? I've been looking myself, but haven't come
across anything forbidding it as of yet.
The Standard says that evaluating an indeterminately-valued object gives
you undefined behaviour - which, presumably, you don't want.

Okay, we've blown away malloc(*ptr), I hope.

Now let's plug in its replacement:

ptr = malloc(n * sizeof *ptr);

(n * can be omitted if it's 1, and sizeof *ptr must be replaced with some
other value - typically 1 - if ptr is of type void *)

Here, *ptr is *not* a pointer dereference, no matter how it looks, because
sizeof DOES NOT EVALUATE ITS OPERAND (except in one weird case in C99
which we can ignore in this discussion, partly because this isn't that
case, and partly because you're probably not using C99 anyway).

The advantage of this over malloc(n * sizeof(type)) is that, even if the
type of ptr changes during maintenance (as long as it doesn't change in or
out of void *), the line doesn't need to be fixed - it adjusts to the new
type's size automatically.

--
Richard Heathfield <http://www.cpax.org.uk >
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Aug 25 '08 #5
Micheal Smith <xu****@cheapbs d.netwrites:
I recently read an article containing numerous gripes about common C
practices. One of them contained a gripe about the use of the sizeof
operator as an argument to malloc calls. The supposed "right" way to go
about calling malloc instead is to dereference a pointer; apparently even
if said pointer is undefined.

E.g.
ptr = malloc(sizeof(s truct some_struct)); = wrong

ptr = malloc(*ptr); = right

The method works on my platform, but doesn't really sit right with me. Is
the code portable? Standard? I've been looking myself, but haven't come
across anything forbidding it as of yet.
As you acknowledged later in the thread, the correct form is

ptr = malloc(sizeof *ptr);

or, if you're uncomfortable with using sizeof without parentheses:

ptr = malloc(sizeof(* ptr));

Or if you want to allocate an array:

ptr = malloc(N * sizeof *ptr);

As "fjblurt" pointed out, this has the advantage that it's obvious
you're using the correct type; if during later maintenance you change
ptr from a foo* to a bar*, the malloc call will continue to be
correct.

The trick here is that the pointer isn't actually dereferenced. The
operand of a sizeof operator is not evaluated; it's only used to
determine the type of the expression. (Variable-length arrays, or
VLAs, a new features in C99, are an exception to this.) So the
expression ``sizeof *ptr'' is guaranteed not to attempt to dereference
ptr. It doesn't even evaluate the pointer value itself.

Your discomfort over what looks like deferencing a possibly invalid
pointer is reasonable, but it's perfectly safe in this case.

--
Keith Thompson (The_Other_Keit h) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Aug 25 '08 #6

Keith Thompson <ks***@mib.orgw rote in message
news:ln******** ****@nuthaus.mi b.org...
Micheal Smith <xu****@cheapbs d.netwrites:
I recently read an article containing numerous gripes about common C
practices. One of them contained a gripe about the use of the sizeof
operator as an argument to malloc calls. The supposed "right" way to go
about calling malloc instead is to dereference a pointer; apparently
even
if said pointer is undefined.

E.g.
ptr = malloc(sizeof(s truct some_struct)); = wrong

ptr = malloc(*ptr); = right

The method works on my platform, but doesn't really sit right with me.
Is
the code portable? Standard? I've been looking myself, but haven't
come
across anything forbidding it as of yet.

As you acknowledged later in the thread, the correct form is

ptr = malloc(sizeof *ptr);

or, if you're uncomfortable with using sizeof without parentheses:

ptr = malloc(sizeof(* ptr));

Or if you want to allocate an array:

ptr = malloc(N * sizeof *ptr);

As "fjblurt" pointed out, this has the advantage that it's obvious
you're using the correct type; if during later maintenance you change
ptr from a foo* to a bar*, the malloc call will continue to be
correct.

The trick here is that the pointer isn't actually dereferenced. The
operand of a sizeof operator is not evaluated; it's only used to
determine the type of the expression. (Variable-length arrays, or
VLAs, a new features in C99, are an exception to this.) So the
expression ``sizeof *ptr'' is guaranteed not to attempt to dereference
ptr. It doesn't even evaluate the pointer value itself.

Your discomfort over what looks like deferencing a possibly invalid
pointer is reasonable, but it's perfectly safe in this case.
Of course it looks like it is de-referencing the pointer, because that's
what de-referencing a pointer looks like everywhere else in "C" code.

At the risk of repeating myself, I'm going to repeat myself:

"It's completely friggin' impossible to learn all the bass-ackwards
and semi-sideways inconsistent methods of declaring and
dereferencing pointers in "C". NO non-lunatic has ever been able
to grasp the total non-logic of the topic, which is just one
incomprehensibl e aspect of an ostensible "programmin g language"
that was obviously actually designed as a cruel joke on anybody
who would attempt to use it (I can just hear the uber-techno-trolls
K&R sniggering about it now)..."

If you DO choose to use this so-called "language", NEVER blame
yourself if you get massively confused by this type of inconsistent
syntax, IT'S NOT YOUR FAULT, YOU'VE BEEN "KERNIGHANE D
AND RITCHIED", PUNK...

---
William Ernest Reid
Aug 26 '08 #7
fjbl...@yahoo.c om wrote:
Micheal Smith <xul...@cheapbs d.netwrote:
[asking about difference between `ptr = malloc(sizeof(
struct some_struct))' and `ptr = malloc(sizeof(* ptr))']

The disadvantage of the first form is that it is up to the
programmer to ensure that the type given in the call to
malloc() agrees with the type in the declaration of ptr.
Quite so. There is more chance of success with...

ptr = (struct some_struct *) malloc(sizeof *ptr);
>*If I inadvertently write

struct other_struct *ptr;

ptr = malloc(sizeof(s truct some_struct));

this code is almost certainly not what I want, but the
compiler will not tell me anything is wrong.*On the other
hand, if I use the second form, there is no possibility
of a mismatch,
Er... did you jut say no possibility? What about...

int *ptr; /* int should be long */
ptr = malloc(*ptr);

The second form can be justifiably preferred, but it is
not foolproof, no method is.
and if I later change the type from 'struct some_struct'
to `struct third_struct', I only have to change it in
one place.
--
Peter
Aug 26 '08 #8
Peter Nilsson <ai***@acay.com .auwrites:
fjbl...@yahoo.c om wrote:
>Micheal Smith <xul...@cheapbs d.netwrote:
[asking about difference between `ptr = malloc(sizeof(
struct some_struct))' and `ptr = malloc(sizeof(* ptr))']

The disadvantage of the first form is that it is up to the
programmer to ensure that the type given in the call to
malloc() agrees with the type in the declaration of ptr.

Quite so. There is more chance of success with...

ptr = (struct some_struct *) malloc(sizeof *ptr);
How is the cast helpful?
>>*If I inadvertently write

struct other_struct *ptr;

ptr = malloc(sizeof(s truct some_struct));

this code is almost certainly not what I want, but the
compiler will not tell me anything is wrong.*On the other
hand, if I use the second form, there is no possibility
of a mismatch,

Er... did you jut say no possibility? What about...

int *ptr; /* int should be long */
ptr = malloc(*ptr);

The second form can be justifiably preferred, but it is
not foolproof, no method is.
The error is in the declaration of ptr, not in the call to malloc.

[...]

--
Keith Thompson (The_Other_Keit h) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Aug 26 '08 #9
Peter Nilsson wrote:
Quite so. There is more chance of success with...

ptr = (struct some_struct *) malloc(sizeof *ptr);
^^^^^^^^^^^^^^^ ^^^^^^

The case is unnecessary, as well as poor programing practice in C.

Er... did you jut say no possibility? What about...

int *ptr; /* int should be long */
ptr = malloc(*ptr);
This is not a problem with the proper use of malloc, but with the
programmer having no clue what type to use. Maybe he should take yp
canasta,
The second form can be justifiably preferred, but it is
not foolproof, no method is.
If you hire monkeys instead of programmers, that's your problem.
Aug 26 '08 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.