(FAQ details:) malloc(), void * and casts

G

Guest

This topic is a FAQ. But I have read the faq and spent a couple of
hours browsing the group archives, and still have a few questions that
I hope you can answer.

My understanding is that recommended practice is to not cast the
return value from malloc(). The rationale for this is that 1) the
cast is not needed and 2) the cast may mask errors.

I assume that the reason the cast is not needed has to do with the
fact that the the pointer returned from malloc() is a void *, and not
a pointer to any other type. (Is that correct?)

If so, could you explain _why_ (and the details of why) casting the
void pointer is not necessary?
(For my naive eye, assigning a pointer of one type (void) to a pointer
of another type (e.g. int) does not seem quite "correct".)

I do have the spec (ISO 9899:1999) at my desk, but I am not familiar
enough with it to find the answer to this one. So references to the
spec, possibly along with some interpretation, would also be helpful.


With kind regards
Asbjørn Sæbø
 
M

Mark Bluemel

Asbjørn Sæbø said:
My understanding is that recommended practice is to not cast the
return value from malloc(). The rationale for this is that 1) the
cast is not needed and 2) the cast may mask errors.

That is so.
I assume that the reason the cast is not needed has to do with the
fact that the the pointer returned from malloc() is a void *, and not
a pointer to any other type. (Is that correct?)
Precisely.

If so, could you explain _why_ (and the details of why) casting the
void pointer is not necessary?

Because according to the standard, pointer to void can be converted to
and from any other object pointer type.
(For my naive eye, assigning a pointer of one type (void) to a pointer
of another type (e.g. int) does not seem quite "correct".)

It's (part of) what the standard intended void * to be used for, as I
understand it.
I do have the spec (ISO 9899:1999) at my desk, but I am not familiar
enough with it to find the answer to this one. So references to the
spec, possibly along with some interpretation, would also be helpful.

Section 6.3.2.3 is fairly clear, I think.
 
R

Richard Tobin

Asbjørn Sæbø said:
If so, could you explain _why_ (and the details of why) casting the
void pointer is not necessary?
(For my naive eye, assigning a pointer of one type (void) to a pointer
of another type (e.g. int) does not seem quite "correct".)

The purpose of the void pointer type is to hold pointers that are
really of another type. There's nothing you do with a void pointer
itself except pass it around and convert it to other types.

Converting between other pointer types on the other hand is unusual,
something you want to think twice about. It's reasonable to have to
be explicit about it if that's what you really want to do.

-- Richard
 
R

Richard Tobin

If so, could you explain _why_ (and the details of why) casting the
void pointer is not necessary?
[/QUOTE]
Because according to the standard, pointer to void can be converted to
and from any other object pointer type.

This isn't sufficient explanation. The same is true of character
pointer types, but you do need a cast there.
It's (part of) what the standard intended void * to be used for, as I
understand it.

This is better. Converting to and from void * isn't just legal, it's
what you're meant to do.

-- Richard
 
R

Richard

Asbjørn Sæbø said:
This topic is a FAQ. But I have read the faq and spent a couple of
hours browsing the group archives, and still have a few questions that
I hope you can answer.

My understanding is that recommended practice is to not cast the
return value from malloc(). The rationale for this is that 1) the
cast is not needed and 2) the cast may mask errors.

I assume that the reason the cast is not needed has to do with the
fact that the the pointer returned from malloc() is a void *, and not
a pointer to any other type. (Is that correct?)

If so, could you explain _why_ (and the details of why) casting the
void pointer is not necessary?
(For my naive eye, assigning a pointer of one type (void) to a pointer
of another type (e.g. int) does not seem quite "correct".)

It isn't. And so the C language does the conversion for you using an
implicit conversion. (I think thats the terminology...)

http://www.stanford.edu/~blp/writings/clc/malloc-cast.html
http://www.cpax.org.uk/prg/writings/casting.php
 
G

Guest

Mark Bluemel said:
Asbjørn Sæbø wrote:

[Why it it not necessary to cast the return value from malloc() ]
If so, could you explain _why_ (and the details of why) casting the
void pointer is not necessary?

Because according to the standard, pointer to void can be converted to
and from any other object pointer type.
[...]
Section 6.3.2.3 is fairly clear, I think.

"A pointer to void may be converted to or from a pointer to any
incomplete or object type. [...]"

And this conversion is implicit? And it is "kosher" in every way, and
should not elicit any warnings ("diagnostics"?) from the compiler?

The reason I ask is that I have been told that at least the Lint we
use at work will object to assigning a void* to e.g. an int *.

Asbjørn
 
M

Mark Bluemel

Asbjørn Sæbø said:
Mark Bluemel said:
Asbjørn Sæbø wrote:

[Why it it not necessary to cast the return value from malloc() ]
If so, could you explain _why_ (and the details of why) casting the
void pointer is not necessary?
Because according to the standard, pointer to void can be converted to
and from any other object pointer type.
[...]
Section 6.3.2.3 is fairly clear, I think.

"A pointer to void may be converted to or from a pointer to any
incomplete or object type. [...]"

And this conversion is implicit?

If by that you mean you can simply assign a void * to an int *, yes.
And it is "kosher" in every way, and
should not elicit any warnings ("diagnostics"?) from the compiler?

Compilers can choose to warn you about just about anything, I believe.

But such code is strictly compliant.
The reason I ask is that I have been told that at least the Lint we
use at work will object to assigning a void* to e.g. an int *.

Then that lint is broken, IMHO. In ISO C (C++ is different), the direct
assignment is, in your words, "kosher" and is to be preferred to
casting, as casting can hide errors.

I recently spent a significant amount of time chasing a such an error -
lack of a prototype meant that the compiler took the return result of a
function as "int" (32-bits), that was cast to "int *" (64-bits) and half
the pointer was missing. Naturally the program crashed.

Without the unnecessary cast, the error would have been picked up much
earlier.
 
K

Keith Thompson

Mark Bluemel said:
Asbjørn Sæbø wrote: [...]
If so, could you explain _why_ (and the details of why) casting the
void pointer is not necessary?

Because according to the standard, pointer to void can be converted to
and from any other object pointer type. [...]
Section 6.3.2.3 is fairly clear, I think.

Yes, but that just says which conversions are allowed (and what they
mean), not which ones can be done implicitly.

6.5.16.1p1 describes the constraints for simple assignment, one of
which is:

one operand is a pointer to an object or incomplete type and the
other is a pointer to a qualified or unqualified version of void,
and the type pointed to by the left has all the qualifiers of the
type pointed to by the right

and paragraph 2 says:

In simple assignment (=), the value of the right operand is
converted to the type of the assignment expression and replaces
the value stored in the object designated by the left operand.

This is what allows a conversion (in either direction) between void*
and another pointer type (other than a pointer-to-function type) to be
performed implicitly.

There are similar rules for initialization and argument passing.

<OT>C++ has different rules.</OT>
 
P

Paul Hsieh

This topic is a FAQ. But I have read the faq and spent a couple of
hours browsing the group archives, and still have a few questions that
I hope you can answer.

My understanding is that recommended practice is to not cast the
return value from malloc(). The rationale for this is that 1) the
cast is not needed and 2) the cast may mask errors.

Right. As you can see 1) is not actually a rationale at all -- its
just a confirmation that it happens to be legal due to the original
design of C, and therefore possible. Its like recommending that you
eat a gallon of whip cream every day because its possible. And 2)
simply does not apply at all on modern compilers -- pretty much every
compiler I use will warn me if I fail to include <stdlib.h> and yet
use malloc().

This "recommendation" does not have any further basis to it. It also
ignores the obvious counter argument that the cast is necessary to
make the same code compatible with C and C++ (a useful thing, that is
in common practice). Many C++ compilers have vastly superior warnings
and can commonly produce better code, so it very often pays to compile
your ANSI C code with a C++ compiler. C++ compilers, these days, are
better maintained than C compilers.
I assume that the reason the cast is not needed has to do with the
fact that the the pointer returned from malloc() is a void *, and not
a pointer to any other type. (Is that correct?)

Right. void * is automatically coercible to any data pointer type in
C. (It is not in C++, and requires explicit casting.)
If so, could you explain _why_ (and the details of why) casting the
void pointer is not necessary?

The standard happens to allow this. Its a legacy thing -- in the past
(before vendors supported the ANSI standard) some compilers used to
allow coercion of any pair of pointers.
(For my naive eye, assigning a pointer of one type (void) to a pointer
of another type (e.g. int) does not seem quite "correct".)

Well, one way or another the result starting from malloc is a void *
anyways. Casting it doesn't change the real result, it just forces
the compiler to copy pointers of one type into pointers of a different
type because that's just the way C is.

But, with very simple use of macros on top of malloc, its possible to
synchronize the size of what you are allocating with the type of what
you are allocating (arrays need some extra consideration) which allows
you to ignore ANSI C's "extra flexibility" and retain a type-safe
subset of the language without losing relevant functionality.
I do have the spec (ISO 9899:1999) at my desk, but I am not familiar
enough with it to find the answer to this one. So references to the
spec, possibly along with some interpretation, would also be helpful.

Just keep in mind that the C spec was written in the 80s for a
language designed in the 70s by hackers borrowing from other languages
who were just throwing it together on their way to designing UNIX. A
lot of the things in that spec are of a "historical" or "legacy"
nature.
 
C

CBFalconer

Paul said:
Right. As you can see 1) is not actually a rationale at all --
its just a confirmation that it happens to be legal due to the
original design of C, and therefore possible. Its like
recommending that you eat a gallon of whip cream every day
because its possible. And 2) simply does not apply at all on
modern compilers -- pretty much every compiler I use will warn
me if I fail to include <stdlib.h> and yet use malloc().

Just a quick reply to warn newbies that this Hsieh post is utter
nonsense. Compilers should not warn when a cast is present,
because the cast says "I know what I am doing, so shut up". Also,
C is not C++. The languages are different, have different rules,
and should be treated differently.
 
P

Peter Nilsson

Mark Bluemel said:
Asbjørn Sæbø said:
Mark Bluemel said:
Asbjørn Sæbø wrote:
...could you explain _why_ (and the details of why)
casting the void pointer is not necessary?

Because according to the standard, pointer to void can
be converted to and from any other object pointer type.
[...]

Section 6.3.2.3 is fairly clear, I think.

"A pointer to void may be converted to or from a pointer
to any incomplete or object type. [...]"

And this conversion is implicit?

If by that you mean you can simply assign a void * to
an int *, yes.
And it is "kosher" in every way,

There are exceptions. For instance...

int *ip; /* uninitialised */
void *vp = ip; /* undefined behaviour */

The conversion is implied, but it needn't be valid for
particular circumstances.

Another example is...

int i;
int *ip = &i;
void *vp = ip; /* fine! */
long *lp = vp; /* potential ub */

Again, the conversions are implicit, but the standard
does not guarantee that the last conversion will
succeed on all implementations. Even on implementations
where the conversion does succeed, the standard does
not guarantee that lp will actually point to ip.

The conversion is not about converting void pointers
arbitrarily, but rather conversions from and _back_ to
the original type and (equivalent) value.

Most implementations of C talk about errors and warnings,
where an error stops compilation (or linking), and a
warning doesn't.

The standard talks of diagnostics, some of which are
required. [Only one required diagnostic need actually
be issued.]

There is no isomorphism between these two concepts. Indeed,
most implementations have mixtures, and all combinations
appear:

Standard Implementation Example (on some systems)
Diagnostic Alert

required warning int *ip = 0xFFFC;

required error int int i;

not required warning while (*s = *p)

not required error unresolved external identifier

Notice that a cast in the first version will not change
the raw semantics, though it will likely remove the warning.
Compilers can choose to warn you about just about anything,
I believe.

But such code is strictly compliant.

There are still caveats that apply to expressions, even
if the conversion is defined.

I recently spent a significant amount of time chasing a
such an error - lack of a prototype meant that the compiler
took the return result of a function as "int" (32-bits),
that was cast to "int *" (64-bits) and half the pointer was
missing. Naturally the program crashed.

Without the unnecessary cast, the error would have been
picked up much earlier.

But the _root_ cause was the lack of required prototype
within C. C99 doesn't quite go that far, but it does
require a declaration. As a minimum, a function declaration
includes a return type.

You talk about not doing something merely because the
standard allows it. Well, the fact that you're allowed to
not cast the return of malloc, is also thought of as in-
sufficient reason to do so. The (quite deliberate) type
weakness of void pointers is one reason why some people
deliberately cast malloc, even with the include header.

Note that not casting can also conceil an error...

int *p;
p = (double *) malloc(sizeof *p);
*p = 3.14159265358979; /* no bleebs, but wrong in context. */
...

Of course, you won't find much understanding of (let
alone support for) that in clc.

My point is simply that different programmers have
different styles. If you want to be able to understand
a lot different code, you need to understand those
styles, even if you yourself dislike or would never
practice them.
 
L

Lorenzo Villari

And 2) simply does not apply at all on modern compilers -- pretty much
every compiler I use will warn me if I fail to include <stdlib.h> and yet
use malloc().

Yes. In fact I've always wondered why some people continue to say that...
Many C++ compilers have vastly superior warnings
and can commonly produce better code, so it very often pays to compile
your ANSI C code with a C++ compiler. C++ compilers, these days, are
better maintained than C compilers.

Ok for the warnings but:

1) Can you give me one example of better code? That would be
interesting...

2) What do you mean by "mantained". Maybe that we have fewer C compilers
than C++ ones? If this is what you meant, I won't be too happy about
that
Just keep in mind that the C spec was written in the 80s for a
language designed in the 70s by hackers borrowing from other languages
who were just throwing it together on their way to designing UNIX. A
lot of the things in that spec are of a "historical" or "legacy"
nature.

Quite illuminating...
 
J

Julienne Walker

Right. As you can see 1) is not actually a rationale at all -- its
just a confirmation that it happens to be legal due to the original
design of C, and therefore possible. Its like recommending that you
eat a gallon of whip cream every day because its possible.

Actually, it's quite a good rationale when taken with the very solid
advice that casts should be avoided whenever possible (which, I'll
add, is an equally strong recommendation in C++, since you're trying
to advocate C++ compatibility). Why add a redundant cast when it's
completely unnecessary? When someone advocates casting malloc, I'm
reminded of the following abomination:

(void)printf( "blahblahblah\n" );
And 2) simply does not apply at all on modern compilers -- pretty
much every compiler I use will warn me if I fail to include <stdlib.h>
and yet use malloc().

It silences at least one warning on all of my 'modern' compilers.
Personally, I'd rather have the warning than not, so I don't cast when
I can avoid it. Wise programmers don't hide warnings without extremely
good reason.
This "recommendation" does not have any further basis to it. It also
ignores the obvious counter argument that the cast is necessary to
make the same code compatible with C and C++ (a useful thing, that is
in common practice). Many C++ compilers have vastly superior warnings
and can commonly produce better code, so it very often pays to compile
your ANSI C code with a C++ compiler. C++ compilers, these days, are
better maintained than C compilers.

If you want C++, use C++. Trying to write C++ compatible C, while
disturbingly common, is also surprisingly difficult to get right. The
counter argument has less of a foundation than you claim the original
argument to have.

Yes, it is useful to write C++ compatible C. But only occasionally. I
see this as an exception to the rule and not a reason to ignore the
rule.
Just keep in mind that the C spec was written in the 80s for a
language designed in the 70s by hackers borrowing from other languages
who were just throwing it together on their way to designing UNIX. A
lot of the things in that spec are of a "historical" or "legacy"
nature.

...


-Jul
 
P

Paul Hsieh

Yes. In fact I've always wondered why some people continue to say that...

Because they have an agenda to push. There is literally no
justification for this recommendation, except as a way of enforcing a
needless artificial incompatibility with C++.
Ok for the warnings but:

1) Can you give me one example of better code? That would be
interesting...

Urg. I shouldn't have put myself out there, now I can't dig up a
concrete example. I am an avid user of the WATCOM C/C++ compilers.
They decided to supply their C and C++ solutions as two separate
compilers and at various times they have clearly put more effort into
their C++ optimizer. I had some benchmarks somewhere long ago that
demonstrated this.
2) What do you mean by "mantained". Maybe that we have fewer C compilers
than C++ ones? If this is what you meant, I won't be too happy about
that

Well C compilers certainly still exist, and some vendors, like
Microsoft, continue to use a single compiler that compiles both
languages. But GNU, and Watcom have clearly taken the two compiler
approach (but in different ways; GNU uses a common back end, at least
for now.)
 
P

Paul Hsieh

Actually, it's quite a good rationale when taken with the very solid
advice that casts should be avoided whenever possible (which, I'll
add, is an equally strong recommendation in C++, since you're trying
to advocate C++ compatibility).

Without the cast, the code is erroneous and will not compiler on a
correct C++ compiler. In this case the casting is not redundant, as
it specifically create a type check which is realistically helpful in
"cut-paste" situations.
[...] Why add a redundant cast when it's
completely unnecessary? When someone advocates casting malloc, I'm
reminded of the following abomination:

(void)printf( "blahblahblah\n" );

The two have nothing to do with each other. No type checking is
happening here, and there is no functional purpose for it.
It silences at least one warning on all of my 'modern' compilers.

But it is an extraneous warning. You are going to get the warning for
using a function without a prototype or implementation anyways (if you
drop the inclusion of stdlib.h) -- that really what the problem is
anyways, not a pointer/int type mismatch.
Personally, I'd rather have the warning than not, so I don't cast when
I can avoid it. Wise programmers don't hide warnings without extremely
good reason.

Wise or not, redundant and misleading warnings for an error you
already have a warning for is not going to help one iota.
If you want C++, use C++. Trying to write C++ compatible C, while
disturbingly common, is also surprisingly difficult to get right.

What are you talking about? I write code like that, pretty much
exclusively nowadays. Its not challenging in the least. Certainly
consumers of the Better String Library appreciate it.
[...] The
counter argument has less of a foundation than you claim the original
argument to have.

The original justification is blatantly false. My justification
corresponds to real issues, and real code.
 
C

CJ

That is so.


Because according to the standard, pointer to void can be converted to
and from any other object pointer type.

In many older implementations of the standard library, malloc is defined
to return a char * rather than a void *, so including the cast makes
your program more portable.
 
I

Ian Collins

CJ said:
On 13 Nov 2007 at 13:20, Mark Bluemel wrote:

In many older implementations of the standard library, malloc is defined
to return a char * rather than a void *, so including the cast makes
your program more portable.
That's a very rare corner case. Such libraries probably require
malloc.h as well.
 
F

Flash Gordon

Julienne Walker wrote, On 19/11/07 18:49:
Actually, it's quite a good rationale when taken with the very solid
advice that casts should be avoided whenever possible

In fact, you should avoid all code that does not do something useful. It
is more to read that does not help. Casting the result of malloc is one
example where it can actually lead to people not spotting problems.

It should be noted that those most likely not to enable warning about
missing prototypes are also (in my opinion) those most likely to fail to
include stdlib.h and add the cast to "fix" the warning. These people
need to be broken of the habit of adding casts to fix warnings, and
telling them it is OK to cast in the one instance is likely to slow the
breaking of this habit.
(which, I'll
add, is an equally strong recommendation in C++, since you're trying
to advocate C++ compatibility).

The best way to provide compatibility with C++ is normally to compile
your C code as C and use the mechanisms
Why add a redundant cast when it's
completely unnecessary? When someone advocates casting malloc, I'm
reminded of the following abomination:

(void)printf( "blahblahblah\n" );
Agreed.


It silences at least one warning on all of my 'modern' compilers.
Personally, I'd rather have the warning than not, so I don't cast when
I can avoid it. Wise programmers don't hide warnings without extremely
good reason.

Also many compilers will not produce a warning about no prototype on
there default warning levels but *will* provide a warning if there is
stdlib.h has been forgotten and no cast is used.
If you want C++, use C++. Trying to write C++ compatible C, while
disturbingly common, is also surprisingly difficult to get right. The
counter argument has less of a foundation than you claim the original
argument to have.

Indeed. Some code will compile as C or C++ but behave differently
depending on which language you compile it as.
Yes, it is useful to write C++ compatible C. But only occasionally. I
see this as an exception to the rule and not a reason to ignore the
rule.

The only common exception is header files, and those will not in general
include calls to malloc.

Yes, C has a number of problems due to its legacy. However the changes
that mean casting the value returned by malloc is not needed were quite
deliberate not accidents of history.
 
K

Keith Thompson

Paul said:
Because they have an agenda to push. There is literally no
justification for this recommendation, except as a way of enforcing a
needless artificial incompatibility with C++.
[...]

(Context: the issue here is casting or not casting the result of malloc().)

Paul, regardless of the technical merits of your argument, your
assertion that those of us who advocate *not* casting the result of
malloc() do so because of some agenda having to do with C++ is
unsupported and false.

Even assuming, for the sake of argument, that you're right and the rest
of us are wrong, please don't presume to make claims about our motives.

My reasons for not casting the result of malloc() have nothing to do
with C++.
 
K

Keith Thompson

Can be *implicitly* converted.
In many older implementations of the standard library, malloc is defined
to return a char * rather than a void *, so including the cast makes
your program more portable.

Such implementations are obsolete. Though you can't yet depend on C99
conformance, you can (except in very rare circumstances) depend on C90
conformance.

Before C89/C90, there was no standard. Different implementations did
very different things. Catering to *all* variations in pre-ANSI
implementations is extremely difficult and tedious -- which is why the
ANSI standard was so enthusiastically accepted.

When was the last time you actually used an implementation that didn't
have malloc() returning a void* declared in <stdlib.h>?
 

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

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top