to cast or not to cast malloc ?

P

P.J. Plauger

OK, this is my last posting on this topic (promise, I think).

Me too, I hope.
Plauger1 offers the argument that in some special contexts there
is a need for C code that can also be compiled as C++. In that
case, as most participants in the debate have acknowledged,
sticking a cast in front of the malloc return is OK, so long as
we can be sure that stdlib.h has been included. However, this
special case hardly justifies the notion that casting the
return from malloc is in general "good C practice".

Nor did I ever promote casting malloc as general good C practice.
I merely pointed out (repeatedly) that the opposition to casting
malloc has become kneejerk in this forum. I have an active dislike
for any dogma that replaces thought. IM(extensive)E I've encountered
several occasions where it makes good sense to add the casts, and
I tried to describe one or two of them. The kneejerks took these
descriptions as attacks on their beloved style rule (which they
were not), and as rival dogma (which it is not).

FWIW, I would advise most C programmers *not* to cast malloc calls,
for most of the reasons advanced by others in this forum.
Plauger2 (I think) goes further, and bemoans the fact that
automatic conversion from (void *) to (whatever *) was ever
accepted into standard C.

Nope. I never bemoaned it. On the contrary, I helped work out the
rules and voted in favor of adding this capability. The one regret
I expressed is that we used the notation of C++ for this purpose.
Practically every case where we coopted C++ notation and altered
its meaning has proved to be a problem in subsequent years.
To Plauger2 (who may not correspond
to the real P.J. Plauger, but apparently does correspond to
E.R. Tisdale) I say, "Get over it!" Such automatic conversion
_is_ part of ISO/ANSI standard C and has been for well over a
decade. Good C programing is defined in relation to the
actually existing standard, not some people's notion of what
the C standard ought to have been.

Not exactly. It's defined in relation to the C Standard *and the
requirements of a given programming project*. Nothing in the C
Standard says you should format your code neatly. And nothing
says you shouldn't. Yet it is a poor project that has no rules
about code layout. Religious wars have been fought for decades
over the proper placement of braces, in part because there's
often really no compelling reason to favor one scheme over
another -- it all depends on what weights you give a handful
of layout principles. (Again FWIW, I pioneered one of the now
popular styles, known as the Whitesmiths style, but I myself
don't adhere to it slavishly.)

It is a curious failing of techies that they mistake *all*
their opinions as the product of rational thought. We all
think with our hormones from time to time; it really helps to
notice when you're doing so. IME, the zeal with which a techie
defends a debatable opinion varies inversely with its rational
defensibility.

Put your casts, and your braces, where you may. But do please
try to think, from time to time, about *why* you're doing what
you're doing. More to the point, when somebody comes up with
a different set of style rules, consider the possibility that
they might not be completely misguided. You might learn
something.

P.J. Plauger
Dinkumware, Ltd.
http://www.dinkumware.com
 
P

Peter Pichler

Richard Heathfield said:
Either you think it's okay to have an implicit conversion from void * to
some object pointer type or other, or you think it isn't. If you think it
/is/ okay, then what are we arguing about? And if you think it /isn't/ okay
and wish to advocate a "fix", then - for that fix to be /useful/ - it
should surely apply to /all/ functions that return void *, not just one of
them?

Not necessarily. Only to those that he uses ;-)

Not that I agree with MSG on this topic. If it ain't necessary, don't do it.

Peter
 
C

Chris Torek

I wonder, though, if at least some pre-ANSI compilers were a bit lax
about pointer conversions. In particular, I wonder if they allowed
implicit conversions from char* to other object pointer types.

No K&R-1 "white book" C compiler should have done so. Dennis
Ritchie's early C compilers did -- but then, they also did not have
"long" and "unsigned" types, and instead of:

int i = 3;

one wrote:

int i 3;

and the op= assignment operators were all written the other way
around:

i =+ 7; /* to go from 3 to 10 */

Thus, unless you were writing in this early dialect -- in which
case much of your code would not compile on any ANSI C compiler --
you would have had to cast the result of malloc() in many cases.

(Incidentally, I am not sure if "long" and "unsigned" appeared
simultaneously or separately. The old-style operators were still
supported in PCC, which not only had long and unsigned [int], but
also unsigned char, unsigned short, and unsigned long. The old-style
initalization syntax had vanished by then, and if you used the
"standard I/O library" and <stdio.h> -- optional under V6-Unix but
the default by PWB-Unix or so -- you could no longer insert a file
descriptor number as the first argument to printf().)

Another holdover from the "early dialect" days appears in struct
and union member names in Unix-like systems. For instance, "struct
stat", for the POSIX stat() and fstat() calls, has st_mode, st_uid,
st_size, and so on as its members. The st_ prefix is there to
distinguish these members from some other structure that might have
a "mode" or "size" member. In early C, all structure members
occupied a single global namespace, and you could put the name of
a structure after *any* variable, or on the right side of *any*
pointer and "->" operator. One ancient program (the "adb" debugger)
still used this feature even in the late 1980s (until I rewrote
it):

struct { char lo, hi; }; /* little endian */
short val;
...
val = <expr>;
... val.lo ...
... val.hi ...

Amazingly, even as late as 1987 or so, this still worked in the
"PCC" compiler (with warnings).
 
J

Johan Lindh

Chris said:
Keith Thompson said:
I wonder, though, if at least some pre-ANSI compilers were a bit lax
about pointer conversions. In particular, I wonder if they allowed
implicit conversions from char* to other object pointer types.


No K&R-1 "white book" C compiler should have done so. Dennis
Ritchie's early C compilers did -- but then, they also did not have
"long" and "unsigned" types, and instead of:

int i = 3;

one wrote:

int i 3;

and the op= assignment operators were all written the other way
around:

i =+ 7; /* to go from 3 to 10 */

Thus, unless you were writing in this early dialect -- in which
case much of your code would not compile on any ANSI C compiler --
you would have had to cast the result of malloc() in many cases.

(Incidentally, I am not sure if "long" and "unsigned" appeared
simultaneously or separately. The old-style operators were still
supported in PCC, which not only had long and unsigned [int], but
also unsigned char, unsigned short, and unsigned long. The old-style
initalization syntax had vanished by then, and if you used the
"standard I/O library" and <stdio.h> -- optional under V6-Unix but
the default by PWB-Unix or so -- you could no longer insert a file
descriptor number as the first argument to printf().)

Another holdover from the "early dialect" days appears in struct
and union member names in Unix-like systems. For instance, "struct
stat", for the POSIX stat() and fstat() calls, has st_mode, st_uid,
st_size, and so on as its members. The st_ prefix is there to
distinguish these members from some other structure that might have
a "mode" or "size" member. In early C, all structure members
occupied a single global namespace, and you could put the name of
a structure after *any* variable, or on the right side of *any*
pointer and "->" operator. One ancient program (the "adb" debugger)
still used this feature even in the late 1980s (until I rewrote
it):

struct { char lo, hi; }; /* little endian */
short val;
...
val = <expr>;
... val.lo ...
... val.hi ...

Amazingly, even as late as 1987 or so, this still worked in the
"PCC" compiler (with warnings).

Is there a good book you could recommend about the history of C?

/J
 
M

Martin Ambuhl

MSG wrote:

2. Make code more readable

The use of malloc is idiomatic C, understood and read by any C programmer.
It is just silly to claim that your non-idiomatic stuff is "more readable."
It is _less_ readable to any C programmer.
3. Prevent size errors like

double * y = /* whatever */ malloc(sizeof(float) * 1000);
/* decided to change precision, forgot to change mallocs */

This is just stupid. Writing it as
double *y = malloc(1000 * sizeof *y);
solves this problem without introducing your NEW layer of obfuscation.
or
float * x = /* whatever */ malloc(sizeof(*x) * 1000);
double * y = /* whatever */ malloc(sizeof(*x) * 1000);
/* copied the line, forgot to change x (or type) */
or
float * x = /* whatever */ malloc(1000 * bla * foo / baz)
/* forgot sizeofs in all of the excitement */

No solution exists to mindless copy-and-paste. Introducing a non-idiomatic
layer on top of C will not help.
It's a win-win-win-win-win situation.

If your definition of "win" is introducing non-idiomatic obfuscating layers
which solve nothing. Your "solution" is a quadruple loser.
 
M

MSG

Richard Heathfield said:
It's not clear what you mean. If you esteem my opinion, why not listen to
it? If you esteem Mr Tisdale's opinion, you don't know him well enough.

Dear Sir,

I apologise if I somehow lead you to believe that you opinion is any
less esteemed than that of ER. Both of your opinions are very highly
esteemed. In fact, they are esteemed so much, that I have difficulty
esteeming them both at the same time, which is not unlike enjoying
intercourse and skydiving simultaneously.

Sincerely,
MSG
 
R

Richard Heathfield

MSG said:
Dear Sir,

I apologise if I somehow lead you to believe that you opinion is any
less esteemed than that of ER. Both of your opinions are very highly
esteemed. In fact, they are esteemed so much, that I have difficulty
esteeming them both at the same time, which is not unlike enjoying
intercourse and skydiving simultaneously.

Good grief; chalk up another correct statement to ERT. This MSG guy /is/ a
troll.
 
A

Allin Cottrell

Sidney said:
Are you implying that ERT could be impersonating Mr. Plauger? That's a
very serious allegation...

No, no, I'm not saying that ERT is sending to the newgroup posts that
purport to be from Mr Plauger. I'm saying that ERT is taking certain
statements made by Mr Plauger and bending them in his own favored
direction, thus making a spurious appeal to authority.

This interpretation seems to be corroborated by Mr Plauger's contribution
downthread.
 
E

E. Robert Tisdale

Allin said:
No, no, I'm not saying that ERT is sending to the newgroup posts
that purport to be from Mr Plauger.
I'm saying that ERT is taking certain statements made by Mr Plauger
and bending them in his own favored direction,
thus making a spurious appeal to authority.
This interpretation seems to be corroborated
by Mr Plauger's contribution downthread.

You certainly *should* check my understanding of what Plauger said
against what Plauger actually said.
Plauger's remarks are a part of the public record.
Take a look a Google Groups:

http://groups.google.com/

Newsgroups: comp.lang.c
Date: 2004-01-25 08:18:38 PST
Subject: Re: why is casting malloc a bad thing?
P.J. Plauger said:
> And the fact remains that the C committee
> made it permissible to omit the cast on a malloc call
> in order to grandfather a gazillion lines of code with malloc calls
> written before we strengthened type checking in C.
> We did so knowing we were blowing a hole in the type checking system
> [that] we cribbed from C++.
 
D

Dik T. Winter

> I wonder, though, if at least some pre-ANSI compilers were a bit lax
> about pointer conversions. In particular, I wonder if they allowed
> implicit conversions from char* to other object pointer types.

Most early compilers allowed all kinds of coversions of pointer types
without cast. Your remark:
> On my old SunOS 4.1 system (circa 1990), malloc() is declared to
> return char*, and the pre-ANSI C compiler issues a warning: "illegal
> pointer combination" on an assignment of the result of malloc() to an
> int*.

This is just a warning, conversion is allowed.

This kind of warnings and the real distinction between different kinds
of pointers came about when C was implemented on systems where different
kinds of pointers also did have different layouts. If I remember right,
even the cast was not in early versions of C.
 
K

Keith Thompson

E. Robert Tisdale said:
You certainly *should* check my understanding of what Plauger said
against what Plauger actually said.
Plauger's remarks are a part of the public record.
Take a look a Google Groups:

http://groups.google.com/

Newsgroups: comp.lang.c
Date: 2004-01-25 08:18:38 PST
Subject: Re: why is casting malloc a bad thing?
P.J. Plauger said:
And the fact remains that the C committee
made it permissible to omit the cast on a malloc call
in order to grandfather a gazillion lines of code with malloc calls
written before we strengthened type checking in C.
We did so knowing we were blowing a hole in the type checking system
[that] we cribbed from C++.

Uh huh. And here's what he wrote more recently in
<[email protected]>:
] FWIW, I would advise most C programmers *not* to cast malloc calls,
] for most of the reasons advanced by others in this forum.

(Yes, that quotation is slightly out of context.)
 
S

Sidney Cadot

Allin said:
No, no, I'm not saying that ERT is sending to the newgroup posts that
purport to be from Mr Plauger.

Okay, just checking to avoid confusion. Thanks for clearing that up.

Best regards,

Sidney
 
J

Jeremy Yallop

Chris said:
I seem to recall that "Expert C Programming" had some of this, but
someone made off with my copy ages ago. The best place is probably
Dennis Ritchie's writings, which are not in book form (as far as I
know) but are available on the web:
<http://cm.bell-labs.com/cm/cs/who/dmr/index.html>.

There's an article by Dennis Ritchie on the history of C in /The
Handbook of Programming Languages/, volume II. I think it's the same
as one of the online articles, but I don't have the details to hand.

Jeremy.
 
J

Johan Lindh

Chris said:
Is there a good book you could recommend about the history of C?


I seem to recall that "Expert C Programming" had some of this, but
someone made off with my copy ages ago. The best place is probably
Dennis Ritchie's writings, which are not in book form (as far as I
know) but are available on the web:
<http://cm.bell-labs.com/cm/cs/who/dmr/index.html>.[/QUOTE]

Thanks!

I found a good page at <http://cm.bell-labs.com/cm/cs/who/dmr/chist.html>.

I wonder what BCPL is an acronym for?

/J
 
K

Kelsey Bjarnason

Both P. J. Plauger and Bjarne Stroustrup disagree with you.
It isn't good code.

Not sure which part isn't good code. Let's see:

1) It avoids the casting of malloc
2) It avoids the problem of x's type changing and having to change the
type in two places (a la malloc( n * sizeof(int) )
3) It works
4) It's readable
5) Aside from having n and sizeof * x backwards, it's largely idiomatic

Now, as to your point. You seem to be committing a fallacy, specifically
an argument from authority: "So-and-so says it's better, and he's an
expert". Problem with that is, an argument sinks or swims on its own
merits, not based on whomever happens to agree with it.

If the above line is bad code, you'll have to supply reasons why, not
merely a shopping list of whomever chooses to agree with you.
 
E

E. Robert Tisdale

Kelsey said:
Not sure which part isn't good code. Let's see:

1) It avoids the casting of malloc
2) It avoids the problem of x's type changing and having to change the
type in two places (a la malloc( n * sizeof(int) )
3) It works
4) It's readable
5) Aside from having n and sizeof * x backwards, it's largely idiomatic

Now, as to your point. You seem to be committing a fallacy,
specifically an argument from authority:

You probably meant "Appeal to Authority".

http://www.don-lindsay-archive.org/skeptic/arguments.html#authority
"So-and-so says it's better, and he's an expert".

Please note that *I* never made such a claim.
Problem with that is, an argument sinks or swims on its own merits,
not based on whomever happens to agree with it.

I agree. Unfortunately, it appears that too many subscribers
to the comp.lang.c newsgroup are easily swayed by fallacious arguments.
If the above line is bad code, you'll have to supply reasons why,
not merely a shopping list of whomever chooses to agree with you.

Not me! My position is more moderate. It's a style issue.
You should consult with Plauger and Stroustrup.
(Plauger has since "clarified" his position (somewhat).)
Both are proponents of strong type checking
and the implicit conversion from void* to any other pointer type
is vexing to them. My C++ compiler complains about the missing cast
and Plauger would rather that the ANSI/ISO C standard require the cast
but decided that it wasn't practical because it would "break"
millions of lines of existing C code.
 
D

Dan Pop

In said:
No K&R-1 "white book" C compiler should have done so.

Except for Ritchie's own compiler ;-) Quoting from page 192:

The compilers currently allow a pointer to be assigned to an integer,
an integer to a pointer, and a pointer to a pointer of another type.
The assignment is a pure copy operation, with no conversion.

He then goes on to explain why well written code shouldn't rely on this
behaviour.

Dan
 

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,764
Messages
2,569,567
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top