Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Casting malloc pointer...

1 view
Skip to first unread message

Paulo J. Matos aka PDestroy

unread,
Apr 26, 2001, 2:59:51 PM4/26/01
to
Hi all,
Just a question on style and 'good programming'
(huh, good programming? what's this? I must be on
my bad days... LOL)

I usually when I want to malloc I just do the
following, for example:
char *s;
s = malloc(20);

I read somewhere... hummm, I remember, on the
Debug Malloc Library documentation
(http://dmalloc.com) that it'd be better to:
char *s;
s = (char *) malloc(20);

i.e., cast the malloc pointer... What's your
oppinion bout this?
They mention this as documenting the code better.
What do you think?

K&R does cast the malloc pointer.
Tommorrow, I'll get my C Unleashed copy to check
out how they do there. Seems to me that I'll
change my C programming style with this... :)


Best regards,

Paulo J. Matos aka PDestroy
http://www.pdestroy.net
ICQ UIN - 361853

Joona I Palaste

unread,
Apr 26, 2001, 3:17:37 PM4/26/01
to
Paulo J. Matos aka PDestroy <pdes...@netcabo.pt> scribbled the following:

> Hi all,
> Just a question on style and 'good programming'
> (huh, good programming? what's this? I must be on
> my bad days... LOL)

> I usually when I want to malloc I just do the
> following, for example:
> char *s;
> s = malloc(20);

> I read somewhere... hummm, I remember, on the
> Debug Malloc Library documentation
> (http://dmalloc.com) that it'd be better to:
> char *s;
> s = (char *) malloc(20);

> i.e., cast the malloc pointer... What's your
> oppinion bout this?
> They mention this as documenting the code better.
> What do you think?

> K&R does cast the malloc pointer.
> Tommorrow, I'll get my C Unleashed copy to check
> out how they do there. Seems to me that I'll
> change my C programming style with this... :)

This is one of the areas that we here can give a definite answer on.
You should NOT cast malloc values! If http://dmalloc.com does it, then
they're clueless. If K&R do it, then that's because they wrote their
book before ISO standardised C.
The CORRECT way to use malloc() is to put #include <stdlib.h> at the
top of your source file (or failing that, provide the prototype
void *malloc(size_t size); yourself), and omit all casts from all
malloc() calls.
The heart of our argument is that the value returned by malloc() should
never, ever, not NO NEVER be even temporarily assigned the type int. If
you don't provide the correct prototype for malloc(), this condition
will not be satisfied. Adding a cast does not help, because it doesn't
remove the conversion from pointer to int, it just converts the int back
into a pointer.

--
/-- Joona Palaste (pal...@cc.helsinki.fi) ---------------------------\
| Kingpriest of "The Flying Lemon Tree" G++ FR FW+ M- #108 D+ ADA N+++|
| http://www.helsinki.fi/~palaste W++ B OP+ |
\----------------------------------------- Finland rules! ------------/

"I am looking for myself. Have you seen me somewhere?"
- Anon

Eric Gorr

unread,
Apr 26, 2001, 3:41:10 PM4/26/01
to
Paulo J. Matos aka PDestroy <pdes...@netcabo.pt> wrote:

> (http://dmalloc.com) that it'd be better to:
> char *s;
> s = (char *) malloc(20);

Casting the malloc pointer isn't recommended here, nor is it necessary.

--
== Eric Gorr ===== http://home.cox.rr.com/ericgorr ===== ICQ:9293199 ===
"Therefore the considerations of the intelligent always include both
benefit and harm." - Sun Tzu
== Insults, like violence, are the last refuge of the incompetent... ===

Brian B. Rodenborn

unread,
Apr 26, 2001, 3:43:30 PM4/26/01
to
In article <3AE87027...@netcabo.pt>,

Paulo J. Matos aka PDestroy <pdes...@netcabo.pt> wrote:

>I read somewhere... hummm, I remember, on the
>Debug Malloc Library documentation
>(http://dmalloc.com) that it'd be better to:
>char *s;
>s = (char *) malloc(20);
>
>i.e., cast the malloc pointer... What's your
>oppinion bout this?
>

>K&R does cast the malloc pointer.

But if you check the errata page online at:

http://cm.bell-labs.com/cm/cs/cbook/2ediffs.html

You see:

142: The remark about casting the return value of malloc ("the proper method
is to declare ... then explicitly coerce") needs to be rewritten. The example
is correct and works, but the advice is debatable in the context of the
1988-1989 ANSI/ISO standards. It's not necessary (given that coercion of
void * to ALMOSTANYTYPE * is automatic), and possibly harmful if malloc, or a
proxy for it, fails to be declared as returning void *. The explicit cast can
cover up an unintended error. On the other hand, pre-ANSI, the cast was
necessary, and it is in C++ also.


>Tommorrow, I'll get my C Unleashed copy to check
>out how they do there. Seems to me that I'll
>change my C programming style with this... :)

No need to do that, they do not.

--
My troubles are many They're deep as a well
I swear there ain't no heaven And I pray there ain't no hell
But I'll never know by livin' Only my dyin' will tell
- Laura Nyro (RIP)

Paulo J. Matos aka PDestroy

unread,
Apr 26, 2001, 4:33:21 PM4/26/01
to

Brian B. Rodenborn wrote:

> In article <3AE87027...@netcabo.pt>,
> Paulo J. Matos aka PDestroy <pdes...@netcabo.pt> wrote:
>
>
>> I read somewhere... hummm, I remember, on the
>> Debug Malloc Library documentation
>> (http://dmalloc.com) that it'd be better to:
>> char *s;
>> s = (char *) malloc(20);
>>
>> i.e., cast the malloc pointer... What's your
>> oppinion bout this?
>>
>> K&R does cast the malloc pointer.
>
>
> But if you check the errata page online at:
>
> http://cm.bell-labs.com/cm/cs/cbook/2ediffs.html
>

Didn't know about the errata, thx for the reference... Situation clearer
now...

Best regards,

Paulo


> You see:
>
> 142: The remark about casting the return value of malloc ("the proper method
> is to declare ... then explicitly coerce") needs to be rewritten. The example
> is correct and works, but the advice is debatable in the context of the
> 1988-1989 ANSI/ISO standards. It's not necessary (given that coercion of
> void * to ALMOSTANYTYPE * is automatic), and possibly harmful if malloc, or a
> proxy for it, fails to be declared as returning void *. The explicit cast can
> cover up an unintended error. On the other hand, pre-ANSI, the cast was
> necessary, and it is in C++ also.
>
>
>
>> Tommorrow, I'll get my C Unleashed copy to check
>> out how they do there. Seems to me that I'll
>> change my C programming style with this... :)
>
>
> No need to do that, they do not.


--
+-----------------------------------------------------------------+
|Paulo J. Matos aka PDestroy | ICQ # 361853 | pdes...@netcabo.pt|
| http://www.pdestroy.net | http://iascp.sourceforge.net |
| "Fixed width font LIVEZ!" | http://mega.ist.utl.pt/~pocm |
+-----------------------------------------------------------------+

willem veenhoven

unread,
Apr 26, 2001, 5:04:58 PM4/26/01
to
"Paulo J. Matos aka PDestroy" wrote:
>
> s = malloc(20);
>
> I read somewhere.. hummm, I remember, on the Debug Malloc Library

> documentation (http://dmalloc.com) that it'd be better to:
> char *s;
> s = (char *) malloc(20);

Here we go again, and you probably knew?

I, for one, think it is perfectly legal to cast the return value of
malloc, and maybe even that it constitutes a better programming
style with respect to clarity. Why not explicitly cast the pointer
yourself if the compiler will automatically also do the conversion
for you. After all, over here in Europe, many drivers also like to
drive a car with manual gearbox. That this might cause some problem
if, and only if, you forget to include a header, does not strike me
as an issue of any importance. Just don't forget to include the
header seems to be the easiest way out to me :-)

> K&R does cast the malloc pointer.

And that always maked sense to me, considering the fact that void
pointers do not have an accessible value without casting. If you
know how to use a (typedef unsigned char) BYTE *, there nothing
extra a void * would buy you. But my experience is limited, as I'm
sure some experts will point out - my curiosity is also the main
reason why I'm taking this rather extreme position :-)

> Tommorrow, I'll get my C Unleashed copy to check out how they do
> there. Seems to me that I'll change my C programming style with
> this... :)

Did Richard really pay you for 'this...' :?)

willem

Joona I Palaste

unread,
Apr 26, 2001, 5:31:32 PM4/26/01
to
willem veenhoven <wil...@veenhoven.com> scribbled the following:

> "Paulo J. Matos aka PDestroy" wrote:
>>
>> s = malloc(20);
>>
>> I read somewhere.. hummm, I remember, on the Debug Malloc Library
>> documentation (http://dmalloc.com) that it'd be better to:
>> char *s;
>> s = (char *) malloc(20);

> Here we go again, and you probably knew?

> I, for one, think it is perfectly legal to cast the return value of
> malloc, and maybe even that it constitutes a better programming
> style with respect to clarity. Why not explicitly cast the pointer
> yourself if the compiler will automatically also do the conversion
> for you. After all, over here in Europe, many drivers also like to
> drive a car with manual gearbox. That this might cause some problem
> if, and only if, you forget to include a header, does not strike me
> as an issue of any importance. Just don't forget to include the
> header seems to be the easiest way out to me :-)

Aga... aga... you are forgetting something quite fundamental here,
willem.

Let's explain this in detail.
If you don't provide a prototype for malloc(), the compiler makes one
up for you. It is going to be:
int malloc();
ie. malloc() takes an unspecified amount of parameters, and returns
int. So when you use malloc() in a program without a proper
prototype, the return value is implicitly converted into int. The
following example illustrates this.

/* This is a C program which doesn't #include <stdlib.h> */
int main(void) {
char *c;
c=malloc(100);
free(c);
return 0;
}

Because of the prototype the compiler made up for you, this program
behaves pretty much (if not exactly) if as written:

/* This is a C program which doesn't #include <stdlib.h> */
int main(void) {
char *c;
c=(int)malloc(100);
free(c);
return 0;
}

The compiler groans about the line "c=malloc(100);" because it doesn't
like implicit casting from int to char *. So the naïve programmer adds
an explicit cast:

/* This is a C program which doesn't #include <stdlib.h> */
int main(void) {
char *c;
c=(char *)malloc(100);
free(c);
return 0;
}

This shuts up the compiler due to the "I know what I'm doing" principle.
But the program behaves pretty much (if not exactly) if as written:

/* This is a C program which doesn't #include <stdlib.h> */
int main(void) {
char *c;
c=(char *)((int)malloc(100));
free(c);
return 0;
}

So instead of removing the conversion from a pointer to an int, the
value is converted back into a pointer. The trouble in this is that
the conversion from pointer to int in the first place causes undefined
behaviour, so the program might crash, or do something far worse.

The solution is, of course, not to let the return value of malloc()
ever get to be of type int. This can only be accomplished by supplying
the compiler the correct prototype of malloc(), which is:
void *malloc(size_t size);

>> K&R does cast the malloc pointer.

> And that always maked sense to me, considering the fact that void
> pointers do not have an accessible value without casting. If you
> know how to use a (typedef unsigned char) BYTE *, there nothing
> extra a void * would buy you. But my experience is limited, as I'm
> sure some experts will point out - my curiosity is also the main
> reason why I'm taking this rather extreme position :-)

Void pointers don't have an accessible value without casting, but in
ISO standard C they can be implicitly converted to any other pointers
without casting. The reason K&R did use the cast was that at that
time, ISO standard C didn't exist.

>> Tommorrow, I'll get my C Unleashed copy to check out how they do
>> there. Seems to me that I'll change my C programming style with
>> this... :)

> Did Richard really pay you for 'this...' :?)

Who cares? I'm convinced Richard's book is quite good. No, he's not
paying me anything.

--
/-- Joona Palaste (pal...@cc.helsinki.fi) ---------------------------\
| Kingpriest of "The Flying Lemon Tree" G++ FR FW+ M- #108 D+ ADA N+++|
| http://www.helsinki.fi/~palaste W++ B OP+ |
\----------------------------------------- Finland rules! ------------/

"To know me IS to love me."
- JIPsoft

Mark McIntyre

unread,
Apr 26, 2001, 5:36:46 PM4/26/01
to
On Thu, 26 Apr 2001 23:04:58 +0200, willem veenhoven
<wil...@veenhoven.com> wrote:

>"Paulo J. Matos aka PDestroy" wrote:
>>
>> s = malloc(20);
>>
>> I read somewhere..

>> s = (char *) malloc(20);
>
>Here we go again, and you probably knew?
>
>I, for one, think it is perfectly legal to cast the return value of
>malloc, and maybe even that it constitutes a better programming
>style with respect to clarity.

What, sticking in extra and unneccessary characters makes it clearer?
Let me guess, you like hungarian notation too :->

And how about maintenance?

>Why not explicitly cast the pointer
>yourself if the compiler will automatically also do the conversion
>for you.

on the other hand, WHY cast if the compiler does it. Why not leave
the compiler to do its job?

>> K&R does cast the malloc pointer.
>
>And that always maked sense to me, considering the fact that void
>pointers do not have an accessible value without casting.

However did you read the errata that they published about that ?


--
Mark McIntyre
CLC FAQ <http://www.eskimo.com/~scs/C-faq/top.html>

Bertrand Mollinier Toublet

unread,
Apr 26, 2001, 6:01:20 PM4/26/01
to

Joona I Palaste wrote:

> <...> value is converted back into a pointer. The trouble in this is that


> the conversion from pointer to int in the first place causes undefined
> behaviour, so the program might crash, or do something far worse.
>

Hey, I'm no expert at specs and all (though I've downloaded and read
some of the ISO C standard), so that I'm not to clear how undefined the
behaviour of a conversion from a pointer to an int can be. I would have
thought the pointer caries a value, which is the address of the object it is
pointing to, and that when cast to an int, this int gets that value, and
that's all. I know this is indeed what happens on a SPARC architecture when
using gcc, and I have to admit that I rely on that on this
platform/compiler.

So can you please enlighten me a bit about this "undefined behaviour"
thing and give examples or even just glimpses of how bad it can be to cast a
pointer to an int.

thx

Bertrand

Mark McIntyre

unread,
Apr 26, 2001, 6:21:17 PM4/26/01
to
On Thu, 26 Apr 2001 22:01:20 GMT, Bertrand Mollinier Toublet
<b...@c-cube.com> wrote:

>
>
>Joona I Palaste wrote:
>
>> <...> value is converted back into a pointer. The trouble in this is that
>> the conversion from pointer to int in the first place causes undefined
>> behaviour, so the program might crash, or do something far worse.
>>
>
> Hey, I'm no expert at specs and all (though I've downloaded and read
>some of the ISO C standard), so that I'm not to clear how undefined the
>behaviour of a conversion from a pointer to an int can be.

A pointer is not an int. So when you convert, information may be lost.

>I would have
>thought the pointer caries a value, which is the address of the object it is
>pointing to,

Maybe. In a flat memory model, where addresses are numerical. how
about in x86 segmented mode where a pointer is two numbers? 4567:fe11.
On some other machine, it may be a relative address with the name of
the refernce as text, or some other non-integral value.

>and that when cast to an int, this int gets that value,

Imagine that a pointer is 64 bits, and an int is 32. What happens when
you convert pointer to int, back to pointer ?

>and
>that's all. I know this is indeed what happens on a SPARC architecture when
>using gcc, and I have to admit that I rely on that on this
>platform/compiler.

it may work on your compiler and platform. When Solaris is upgraded
next,. it may break.

> So can you please enlighten me a bit about this "undefined behaviour"
>thing and give examples or even just glimpses of how bad it can be to cast a
>pointer to an int.

hopefully I did that !

Eric Sosman

unread,
Apr 26, 2001, 6:25:04 PM4/26/01
to

Isn't this a FAQ? No; I guess not -- although the thread
about casting malloc's value is; see Questions 7.6 and 7.7 at

http://www.eskimo.com/~scs/C-faq/top.html

As for the specific question about converting between pointer
values and int values, I'll offer two answers, one legalistic and
one practical:

- The Standard tells us that an pointer value can be converted
to an int value and vice versa, but it also tells us that
the results of these conversions is implementation-defined
and not necessarily meaningful; in particular, converting a
pointer value to an int and then back to a pointer might not
yield a valid pointer value. A program which converts an int
to a pointer and then attempts to use the pointer value risks
undefined behavior if the conversion produced an invalid pointer.

- As typically configured, gcc on SPARC uses 32-bit pointers and
32-bit ints. But there are other compilers (including gcc in
some non-default configurations) which use 64-bit pointers and
32-bit ints. I'm sure you can imagine what happens when you
try to convert a 64-bit pointer to a 32-bit int and back again;
the chance of re-forming the original pointer value are roughly
nil. And SPARC is by no means the only CPU architecture on
which pointers are (or can be) larger than ints.

Summary: The fact that you're getting away with something on the
machine and compiler you happen to be using at this moment is no
guarantee that you'll get away with it on tomorrow's machine or
tomorrow's compiler.

--
Eric....@east.sun.com

Dann Corbit

unread,
Apr 26, 2001, 6:59:27 PM4/26/01
to
"Paulo J. Matos aka PDestroy" <pdes...@netcabo.pt> wrote in message
news:3AE87027...@netcabo.pt...

> Hi all,
> Just a question on style and 'good programming'
> (huh, good programming? what's this? I must be on
> my bad days... LOL)
>
> I usually when I want to malloc I just do the
> following, for example:
> char *s;
> s = malloc(20);
>
> I read somewhere... hummm, I remember, on the
> Debug Malloc Library documentation
> (http://dmalloc.com) that it'd be better to:
> char *s;
> s = (char *) malloc(20);
>
> i.e., cast the malloc pointer... What's your
> oppinion bout this?
> They mention this as documenting the code better.
> What do you think?
>
> K&R does cast the malloc pointer.
> Tommorrow, I'll get my C Unleashed copy to check
> out how they do there. Seems to me that I'll
> change my C programming style with this... :)


Pro's:
1. Compatible with C++ (you have to cast a void pointer to any other type).

Cons:
1. Bjarne himself says not to use malloc()/free() but use new/delete instead.
2. It can mask serious errors caused by forgetting to include stdlib.h

From the C FAQ:
7.6: Why am I getting "warning: assignment of pointer from integer
lacks a cast" for calls to malloc()?

A: Have you #included <stdlib.h>, or otherwise arranged for
malloc() to be declared properly? See also question 1.25.

References: H&S Sec. 4.7 p. 101.

7.7: Why does some code carefully cast the values returned by malloc
to the pointer type being allocated?

A: Before ANSI/ISO Standard C introduced the void * generic pointer
type, these casts were typically required to silence warnings
(and perhaps induce conversions) when assigning between
incompatible pointer types.

Under ANSI/ISO Standard C, these casts are no longer necessary,
and in fact modern practice discourages them, since they can
camouflage important warnings which would otherwise be generated
if malloc() happened not to be declared correctly; see question
7.6 above. (However, the casts are typically seen in C code
which for one reason or another is intended to be compatible
with C++, where explicit casts from void * are required.)

References: H&S Sec. 16.1 pp. 386-7.


--
C-FAQ: http://www.eskimo.com/~scs/C-faq/top.html
"The C-FAQ Book" ISBN 0-201-84519-9
C.A.P. FAQ: ftp://cap.connx.com/pub/Chess%20Analysis%20Project%20FAQ.htm


Jack Klein

unread,
Apr 27, 2001, 12:09:14 AM4/27/01
to
On Thu, 26 Apr 2001 22:01:20 GMT, Bertrand Mollinier Toublet
<b...@c-cube.com> wrote in comp.lang.c:

What you are forgetting here is that it is not necessarily a matter of
a pointer being taken for an int, then converted back to a pointer.

There are implementations where pointers and ints are returned from
functions in different registers, or are totally different sizes.

Two very popular platforms for C a decade ago were the 16 bit Intel
x86 processors and the Motorola 68000 series, the latter at one time
the single largest installed platform running UNIX variants.

In some memory models of the Intel x86, ints were 16 bits and returned
in a single 16 bit register. Pointers were 32 bits and returned in
two 16 bit registers, and a compiler might choose to two registers
that didn't include the one that ints were returned in.

So the implicit int of malloc() without a prototype could result in
either one half of the 32 bit pointer being extended with 0 bits and
stored in the destination pointer, with the other half of the pointer
value totally lost. Or it could result is some totally unrelated
value in the integer return register, that had no contained no bits at
all of the pointer, to be extended with 0 bits and stored.

The Motorola architecture on the other hand had its registers divided
into two types, D registers and A registers. D (data) registers could
be used for all types of arithmetic and logical calculations but could
not be used to address memory. A (address) registers can be used for
as many types of calculations, but can hold pointer values and access
memory. Compilers for this architecture could again return ints in
one of the D registers but pointers in one of the A registers. So
again the missing prototype and implicit int would cause a totally
unrelated value from a completely different register to be stored in
the receiving pointer.

Now you might think the days when problems caused by older
architectures like these are dead and gone, you have a modern system
where ints and pointers are both 32 bits, and your compiler chooses to
use the same register to return either one. But actually your modern
system of today will be an obsolete antique in a few years, the 64 bit
processors are coming and so are 64 bit versions of UNIX and Windows.

Just a few weeks ago a very experienced UNIX poster posted a message
in one of the popular C groups, very puzzled. His new 64 bit UNIX box
(I forget if it was Solaris or AIX) crashed instantly when he compiles
his memory allocation test program in 64 bit mode, although it worked
fine in 32 bit mode and allocated hundreds of megabytes.

He posted his complete source, and at the top of the file was an
include for <stdio.h>, but none for <stdlib.h>, and sure enough he
casted the return value of malloc() to a char * in his loop that
allocated blocks until malloc() ran out of memory.

Immediately there were about 15 replies pointing out the missing
<stdlib.h>, and he quickly confirmed that under the 64 bit C compiler,
pointers were 64 bits but ints only 32.

So the next generation of 64 bit Windows, Linux, and UNIX boxes are
going to bring back the old problems of the 16 bit x86 and the
Motorola 68000 platforms, because on most of them ints and pointers
will be different sizes again (32 bit vs. 64 bit), and programs that
omit the prototype and use an explicit cast will stop working by
accident.

How long do you think it will be before you are building 64 bit
programs under 64 bit versions of Solaris to run on 64 bit SPARC
processors? No, it'll probably be sooner than that!

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++ ftp://snurse-l.org/pub/acllc-c++/faq

Dan Pop

unread,
Apr 27, 2001, 7:00:27 PM4/27/01
to

> - The Standard tells us that an pointer value can be converted
> to an int value and vice versa, but it also tells us that
> the results of these conversions is implementation-defined
> and not necessarily meaningful;

The standard also tells us that converting a pointer value to an int can
result in undefined behaviour.

Dan
--
Dan Pop
CERN, IT Division
Email: Dan...@cern.ch
Mail: CERN - IT, Bat. 31 1-014, CH-1211 Geneve 23, Switzerland

0 new messages