By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
457,930 Members | 1,413 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 457,930 IT Pros & Developers. It's quick & easy.

to cast or not to cast malloc ?

P: n/a
MSG
The answer is neither. Use macros.

#define ALLOC(size, type) ((type) *) malloc((size) * sizeof(type))
#define NEW(type, name, size) (type) * (name) = ALLOC((size), (type))

They are both [more] type-safe and concise.

Compare:

NEW(int, x, 1000);

to

int * x = (int*) malloc(sizeof(int) * 1000);
I'm sure someone must have "discovered" this before. Anyways HTH.

MSG
Nov 14 '05 #1
Share this Question
Share on Google+
36 Replies


P: n/a
MSG wrote:
The answer is neither. Use macros.

#define ALLOC(size, type) ((type) *) malloc((size) * sizeof(type))
#define NEW(type, name, size) (type) * (name) = ALLOC((size), (type))

They are both [more] type-safe and concise.

Compare:

NEW(int, x, 1000);

to

int * x = (int*) malloc(sizeof(int) * 1000);
If you must compare, at least compare to good code:

int *x = malloc(sizeof *x * n);
I'm sure someone must have "discovered" this before. Anyways HTH.


Yes, they're hardly new, I'm afraid.

Presumably you have equivalents for all the other functions returning a void
pointer? Not just the standard library functions (memchr, memset, bsearch,
calloc, realloc), but all the third-party libraries, too?

If not, you'd better get busy. When the /whole set/ is completed, fully
tested, and guaranteed by ISO to work correctly, I'll start using them.
Deal?

--
Richard Heathfield : bi****@eton.powernet.co.uk
"Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
K&R answers, C books, etc: http://users.powernet.co.uk/eton
Nov 14 '05 #2

P: n/a
Richard Heathfield wrote:
If you must compare, at least compare to good code:

int *x = malloc(sizeof *x * n);


Both P. J. Plauger and Bjarne Stroustrup disagree with you.
It isn't good code.
It's a bad habit that was "grandfathered" into the standards
so that the standard wouldn't break all of the existing bad code.

Please reference recent articles in the comp.lang.c newsgroup.

Nov 14 '05 #3

P: n/a
On 2004-02-06, E. Robert Tisdale <E.**************@jpl.nasa.gov> wrote:

Both P. J. Plauger and Bjarne Stroustrup disagree with you. It isn't
good code. It's a bad habit that was "grandfathered" into the standards
so that the standard wouldn't break all of the existing bad code.

Please reference recent articles in the comp.lang.c newsgroup.


I trust Steve Summit's opinion far more than I do yours, so the rest of us
will leave off the cast, thanks.

-Clint
Nov 14 '05 #4

P: n/a
E. Robert Tisdale wrote:
Richard Heathfield wrote:
If you must compare, at least compare to good code:

int *x = malloc(sizeof *x * n);

Both P. J. Plauger and Bjarne Stroustrup disagree with you.
It isn't good code.
It's a bad habit that was "grandfathered" into the standards
so that the standard wouldn't break all of the existing bad code.


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

First, my only objection to Richard's example is purely stylistic;
I find it clearer on the eye to write:

int *x = malloc(n * sizeof *x);

rather than

int *x = malloc(sizeof *x * n);

(There's something a little confusing about the two '*'s in close
proximity in the version Richard wote above.)

Second, leave Mr Stroustrup out of it. I'm sure he is (or was) an
expert C programmer, but his commitment to C++ renders him an
unreliable witness in this case (C++ requires that the return of
malloc be cast to the type at issue -- although, as others have
noted, use of malloc is not really idiomatic in C++ anyway).

That leaves the reference to Mr Plauger, who is assuredly an
expert in C. In previous discussions of this point on clc we
can distinguish Plauger1 and Plauger2.

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

Plauger2 (I think) goes further, and bemoans the fact that
automatic conversion from (void *) to (whatever *) was ever
accepted into standard C. 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.

--
Allin Cottrell
Department of Economics
Wake Forest University, NC
Nov 14 '05 #5

P: n/a
Allin Cottrell wrote:
[...] Plauger2 (I think) goes further, and bemoans the fact that
automatic conversion from (void *) to (whatever *) was ever
accepted into standard C. 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.
So are trigraphs. The "because we can" argument is fundamentally
unsound, IMHO. There are several good reasons for not casting malloc
results, but the fact that C /allows/ them to be not casted is not one
of them.
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.


Which one, C89 or C99? Because with C99, the stdlib.h argument (which is
weak already because of modern compilers) goes entirely out the window.

Best regards,

Sidney

Nov 14 '05 #6

P: n/a
Allin Cottrell wrote:
Plauger2 (I think) goes further, and bemoans the fact that
automatic conversion from (void *) to (whatever *)
was ever accepted into standard C.
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.


No.
The standard allows programmers to do all kinds of things
that are *not* necessarily "good programming practice".
C is *not* Ada. C programmers are given a cocked and loaded fire arm
with the safety turned off.
All they need to do is point it at the remaining foot and blow it off.
Good programming practice is the exercise of [self]discipline.

According to Plauger, the implicit conversion from *void
to any other pointer type is the result of poor programming practice
and a lack of [self]discipline. The were compelled to include it
in the standard because so much bad code had already been written.

Nov 14 '05 #7

P: n/a
Sidney Cadot wrote:
Plauger2 (I think) goes further, and bemoans the fact that
automatic conversion from (void *) to (whatever *) was ever
accepted into standard C. 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.


So are trigraphs. The "because we can" argument is fundamentally
unsound, IMHO. There are several good reasons for not casting malloc
results, but the fact that C /allows/ them to be not casted is not one
of them.


The actual nature of C makes the cast redundant. The insertion
of redundant casts -- not their omission -- requires some sort
of special justification. This is my point.
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.


Which one, C89 or C99? Because with C99, the stdlib.h argument (which is
weak already because of modern compilers) goes entirely out the window.


Suppose "the C standard" is some sort of weighted average of C89 and
C99, the weights depending on the context of the discussion. As the
weight on C99 approaches 1.0, the stdlib.h argument approaches
negligibility. The argument that redundant casts are best
avoided retains its full force. The Plauger1 argument that some
code may have to be compiled as C++ retains its orthogonality to
the issue of good C practice. The notion that "we really ought
to have to cast the malloc return and it's a shame we don't"
retains its irrelevance.

--
Allin Cottrell
Department of Economics
Wake Forest University, NC
Nov 14 '05 #8

P: n/a
On Fri, 06 Feb 2004 15:27:19 -0800, "E. Robert Tisdale"
<E.**************@jpl.nasa.gov> wrote in comp.lang.c:
Richard Heathfield wrote:
If you must compare, at least compare to good code:

int *x = malloc(sizeof *x * n);


Both P. J. Plauger and Bjarne Stroustrup disagree with you.
It isn't good code.
It's a bad habit that was "grandfathered" into the standards
so that the standard wouldn't break all of the existing bad code.

Please reference recent articles in the comp.lang.c newsgroup.


Another one of your utterly foolish replies, I'm afraid. Since there
was no void or pointer to void in K&R C, malloc() in those days was
defined as returning a pointer to char. All calls to malloc() that
allocated memory to be used for other types than char required the
cast.

So it is quite obvious that there was nothing to "grandfather" in this
regard.

As for Stroustrup, note that C++ allows the implicit conversion TO
pointer to void FROM pointer to any other object type, as does C, just
not the reverse. The reasoning for this strikes me as a little
suspect. Unlike, I hasten to add, most of Dr. Stroustrup's other
design decisions in the development of C++. Also note that he has
proposed allowing the void pointer to object pointer conversion in a
future version of the C++ standard.

Plauger gave very specific reasons for his preference, and it really
has nothing to do with C and everything to do with C++.

--
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++
http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html
Nov 14 '05 #9

P: n/a
Allin Cottrell wrote:
.... snip ...
Plauger2 (I think) goes further, and bemoans the fact that
automatic conversion from (void *) to (whatever *) was ever
accepted into standard C. 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.


I never noticed that! If true, Trollsdale has learned yet another
evil trick. At any rate the only one who can say for sure is P.J.
Plauger, who should object violently to any such happenings.
Impersonation is not looked upon with favor by ISPs.

In fact, the very continued presence of Trollsdale here tends to
argue against his having practiced such a trick.

--
Chuck F (cb********@yahoo.com) (cb********@worldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!

Nov 14 '05 #10

P: n/a
Allin Cottrell wrote:
E. Robert Tisdale wrote:
Richard Heathfield wrote:
If you must compare, at least compare to good code:

int *x = malloc(sizeof *x * n);

Both P. J. Plauger and Bjarne Stroustrup disagree with you.
It isn't good code.
It's a bad habit that was "grandfathered" into the standards
so that the standard wouldn't break all of the existing bad code.


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

First, my only objection to Richard's example is purely stylistic;
I find it clearer on the eye to write:

int *x = malloc(n * sizeof *x);

rather than

int *x = malloc(sizeof *x * n);


So do I! :-) Again, I've been caught by my tendency to edit the original
code as little as possible (I don't like to insist that people do things my
way).

<snip>

--
Richard Heathfield : bi****@eton.powernet.co.uk
"Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
K&R answers, C books, etc: http://users.powernet.co.uk/eton
Nov 14 '05 #11

P: n/a
E. Robert Tisdale wrote:
Richard Heathfield wrote:
If you must compare, at least compare to good code:

int *x = malloc(sizeof *x * n);
Both P. J. Plauger and Bjarne Stroustrup disagree with you.


I'm sure both gentlemen are capable of speaking for themselves.
It isn't good code.


Your opinion of what constitutes good code is of little or no interest to
me. I prefer the opinion of C experts. Mr Stroustrup is, of course, a C++
expert; Mr Plauger is in fact a C expert, and I would point out that he has
most certainly /not/ said that omitting the cast constitutes bad style. It
is merely something he prefers not to do, for excellent reasons of his own.

<snip>

--
Richard Heathfield : bi****@eton.powernet.co.uk
"Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
K&R answers, C books, etc: http://users.powernet.co.uk/eton
Nov 14 '05 #12

P: n/a
E. Robert Tisdale wrote:

<snip>
According to Plauger, the implicit conversion from *void


Plauger would say no such thing, for the very good reason that C does not
permit the dereferencing of a void object - so there is /no/ implicit
conversion from *void.

--
Richard Heathfield : bi****@eton.powernet.co.uk
"Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
K&R answers, C books, etc: http://users.powernet.co.uk/eton
Nov 14 '05 #13

P: n/a
"E. Robert Tisdale" <E.**************@jpl.nasa.gov> writes:
[...]
The standard allows programmers to do all kinds of things
that are *not* necessarily "good programming practice".
C is *not* Ada.


In that sense, Ada isn't Ada either. I've seem some very ugly Ada
code. There is no programming language that makes it impossible, or
even particularly difficult, to write bad code. (Ada tries to make it
easier to write good code, but that's a topic for another newsgroup.)

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://www.sdsc.edu/~kst>
Schroedinger does Shakespeare: "To be *and* not to be"
Nov 14 '05 #14

P: n/a
Jack Klein <ja*******@spamcop.net> writes:
[...]
Since there was no void or pointer to void in K&R C, malloc() in
those days was defined as returning a pointer to char. All calls to
malloc() that allocated memory to be used for other types than char
required the cast.


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*. Also, the man page for malloc() says:

Note: Always cast the value returned by malloc(), realloc(),
calloc(), memalign(), valloc() or alloca().

(advice that is, of course, no longer as good as it was at the time).

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.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://www.sdsc.edu/~kst>
Schroedinger does Shakespeare: "To be *and* not to be"
Nov 14 '05 #15

P: n/a
MSG
Richard Heathfield <do******@address.co.uk.invalid> wrote in message news:<c0**********@titan.btinternet.com>...
MSG wrote:
The answer is neither. Use macros.

#define ALLOC(size, type) ((type) *) malloc((size) * sizeof(type))
#define NEW(type, name, size) (type) * (name) = ALLOC((size), (type))

They are both [more] type-safe and concise.

Compare:

NEW(int, x, 1000);

to

int * x = (int*) malloc(sizeof(int) * 1000);
If you must compare, at least compare to good code:

int *x = malloc(sizeof *x * n);
I'm sure someone must have "discovered" this before. Anyways HTH.


Yes, they're hardly new, I'm afraid.

Presumably you have equivalents for all the other functions returning a void
pointer?


Some of them.
Not just the standard library functions (memchr, memset, bsearch,
calloc, realloc), but all the third-party libraries, too?
Irrelevant (unless I don't understand what you are saying)
If not, you'd better get busy. When the /whole set/ is completed, fully
tested, and guaranteed by ISO to work correctly, I'll start using them.
Deal?


International law is to complicated to make this deal worthwhile :-)

My point is that by using NEW instead of malloc directly, you

1. Save the typing
2. Make code more readable
3. Prevent size errors like

double * y = /* whatever */ malloc(sizeof(float) * 1000);
/* decided to change precision, forgot to change mallocs */
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 */

4. Have the benefit of being able to easily change your mind
about casting depending on your compiler, language dialect, etc.

It's a win-win-win-win-win situation.

MSG

P.S. Too much ON-topic is boring me, so this thread of over
for me, unless Mr. E.R. Tisdale tells us why they mostly
gave up *Ada* in favor of C/C++ at NASA! (I know why, but
I'm curious about your esteemed opinion)
Nov 14 '05 #16

P: n/a
In 'comp.lang.c', ms*****@yahoo.com (MSG) wrote:
#define ALLOC(size, type) ((type) *) malloc((size) * sizeof(type))
#define NEW(type, name, size) (type) * (name) = ALLOC((size), (type))

They are both [more] type-safe and concise.

Compare:

NEW(int, x, 1000);

to

int * x = (int*) malloc(sizeof(int) * 1000);


What about:

#include <stdlib.h>

#define NEW(type, name, size) \
(type) * (name) = malloc (size * sizeof * (name))

#define DELETE(name)\
free (name), (name) = NULL

NEW (int, px, 1000);

if (px != NULL)
{
DELETE (px);
}

--
-ed- em**********@noos.fr [remove YOURBRA before answering me]
The C-language FAQ: http://www.eskimo.com/~scs/C-faq/top.html
C-reference: http://www.dinkumware.com/manuals/reader.aspx?lib=cpp
FAQ de f.c.l.c : http://www.isty-info.uvsq.fr/~rumeau/fclc/
Nov 14 '05 #17

P: n/a
Allin Cottrell wrote:
Sidney Cadot wrote:
Plauger2 (I think) goes further, and bemoans the fact that
automatic conversion from (void *) to (whatever *) was ever
accepted into standard C. To Plauger2 (who may not correspond
to the real P.J. Plauger, but apparently does correspond to
E.R. Tisdale)
Are you implying that ERT could be impersonating Mr. Plauger? That's a
very serious allegation; if you stand by it, you will need to back it
up. Even hinting at the possibility is possibly slanderous. Especially
in dealing with people of sometimes questionable standards (e.g. ERT's
well-documented quote-altering behavior) it is essential to keep to the
moral high ground.
I say, "Get over it!" Such automatic conversion
_is_ part of ISO/ANSI standard C and has been for well over a
decade.

So are trigraphs. The "because we can" argument is fundamentally
unsound, IMHO. There are several good reasons for not casting malloc
results, but the fact that C /allows/ them to be not casted is not one
of them.


The actual nature of C makes the cast redundant.


This is a bit vague for my taste. The cast is made superfluous by the
standard in typical-use cases, that's something more precise. However,
the standard (I'm talking about C99 now) also makes "return 0;" at the
end of main superfluous. Does that mean I'm going to follow suit? I
think not.

As to your use of the word "redundant": that is too strong for my taste.

malloc(50*sizeof(double))

and

(double *)malloc(50*sizeof(double))

have different types. Ergo, the cast has a function, with regard to this
expression, and it is not redundant.
The insertion of redundant casts -- not their omission --
requires some sort of special justification. This is my point.
Yes. Over and over again, two justifications have been presented, by me
at least:

- making sure that your program is also conforming C++ (if you
want/need this for one reason or another).

- correcting the compiler's misconception about a pointer to an
allocated block of memory at the earliest possible convenience
(which means: prior to the pointer being used in any way,
for example, as the right-hand-side of an assignment).

For me, these are the justification.
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.


Which one, C89 or C99? Because with C99, the stdlib.h argument (which
is weak already because of modern compilers) goes entirely out the
window.

Suppose "the C standard" is some sort of weighted average of C89 and
C99, the weights depending on the context of the discussion.
That sounds like a dangerous path to follow. The first problem is that
there exist no standards for weight values other than 0 and 1. The
second problem is that people can tune the weight to support their
opinion in any given situation. In essence, you're providing a knob that
one can turn to shift the goalposts.
As the
weight on C99 approaches 1.0, the stdlib.h argument approaches
negligibility. The argument that redundant casts are best
avoided retains its full force.
I object to your use of the word "redundant". It is fair to say that the
compiler will perform a conversion of the malloc result soon as a result
of the typical use pattern, where malloc() is used as the RHS of an
assignment, but that's something different entirely from saying the cast
is "redundant".
The Plauger1 argument that some
code may have to be compiled as C++ retains its orthogonality to
the issue of good C practice. The notion that "we really ought
to have to cast the malloc return and it's a shame we don't"
retains its irrelevance.


That's as explicit a restatement of the "because we can" argument as
they come. I whole-heartedly and sincerely disagree.

Best regards,

Sidney

Nov 14 '05 #18

P: n/a
MSG wrote:
Richard Heathfield <do******@address.co.uk.invalid> wrote in message
news:<c0**********@titan.btinternet.com>...
MSG wrote:
> The answer is neither. Use macros.
>
> #define ALLOC(size, type) ((type) *) malloc((size) * sizeof(type))
> #define NEW(type, name, size) (type) * (name) = ALLOC((size), (type))
>
> They are both [more] type-safe and concise.
>
> Compare:
>
> NEW(int, x, 1000);
>
> to
>
> int * x = (int*) malloc(sizeof(int) * 1000);
If you must compare, at least compare to good code:

int *x = malloc(sizeof *x * n);
> I'm sure someone must have "discovered" this before. Anyways HTH.


Yes, they're hardly new, I'm afraid.

Presumably you have equivalents for all the other functions returning a
void pointer?


Some of them.
Not just the standard library functions (memchr, memset, bsearch,
calloc, realloc), but all the third-party libraries, too?


Irrelevant (unless I don't understand what you are saying)


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?
If not, you'd better get busy. When the /whole set/ is completed, fully
tested, and guaranteed by ISO to work correctly, I'll start using them.
Deal?


International law is to complicated to make this deal worthwhile :-)


The point is that you're never going to be able to provide similar solutions
for all the void *-returning functions in the world, because you'll never
even know what they all are.

My point is that by using NEW instead of malloc directly, you

1. Save the typing
Why not call it N, then? You'd save even more typing.
2. Make code more readable
I disagree; malloc is idiomatic, but NEW is not.
3. Prevent size errors like

double * y = /* whatever */ malloc(sizeof(float) * 1000);
But I don't make those errors, because I do:

T *p = malloc(n * sizeof *p);

which is always correct.
/* decided to change precision, forgot to change mallocs */
or
float * x = /* whatever */ malloc(sizeof(*x) * 1000);
double * y = /* whatever */ malloc(sizeof(*x) * 1000);
/* copied the line, forgot to change x (or type) */
That'll teach you to copy-and-paste without thinking.

or
float * x = /* whatever */ malloc(1000 * bla * foo / baz)
/* forgot sizeofs in all of the excitement */

4. Have the benefit of being able to easily change your mind
about casting depending on your compiler, language dialect, etc.
I already have that, because I already use a wrapper. Just not /your/
wrapper. Note that my wrapper does not include a cast.
It's a win-win-win-win-win situation.
So you say.

MSG

P.S. Too much ON-topic is boring me,
Then you're in the wrong newsgroup. comp.lang.c is all about on-topic.
so this thread of over
for me, unless Mr. E.R. Tisdale tells us why they mostly
gave up *Ada* in favor of C/C++ at NASA! (I know why, but
I'm curious about your esteemed opinion)


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.

--
Richard Heathfield : bi****@eton.powernet.co.uk
"Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
K&R answers, C books, etc: http://users.powernet.co.uk/eton
Nov 14 '05 #19

P: n/a
Emmanuel Delahaye wrote:
.... snip ...
What about:

#include <stdlib.h>

#define NEW(type, name, size) \
(type) * (name) = malloc (size * sizeof * (name))

#define DELETE(name)\
free (name), (name) = NULL

NEW (int, px, 1000);

if (px != NULL)
{
DELETE (px);
}

void *p[N], *t;
.....
t = p;
assert(M < N);
p[M] = NULL;
for (i = 0; i < M; i++) NEW(void, t[i], 10);
while (t) DELETE(*t++);

woops!

--
Chuck F (cb********@yahoo.com) (cb********@worldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!
Nov 14 '05 #20

P: n/a
"Allin Cottrell" <co******@wfu.edu> wrote in message
news:c0***********@f1n1.spenet.wfu.edu...
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
Nov 14 '05 #21

P: n/a
"Richard Heathfield" <do******@address.co.uk.invalid> wrote:
MSG wrote:
Richard Heathfield <do******@address.co.uk.invalid> wrote:

Presumably you have equivalents for all the other functions returning a
void pointer?
Some of them.
Not just the standard library functions (memchr, memset, bsearch,
calloc, realloc), but all the third-party libraries, too?


Irrelevant (unless I don't understand what you are saying)


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
Nov 14 '05 #22

P: n/a
In article <ln************@nuthaus.mib.org>
Keith Thompson <ks***@mib.org> writes:
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).
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (4039.22'N, 11150.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Nov 14 '05 #23

P: n/a
Chris Torek wrote:
In article <ln************@nuthaus.mib.org>
Keith Thompson <ks***@mib.org> writes:
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
Nov 14 '05 #24

P: n/a
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.

--
Martin Ambuhl
Nov 14 '05 #25

P: n/a
MSG
Richard Heathfield <do******@address.co.uk.invalid> wrote in message news:<c0**********@titan.btinternet.com>...
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
Nov 14 '05 #26

P: n/a
MSG wrote:
Richard Heathfield <do******@address.co.uk.invalid> wrote in message
news:<c0**********@titan.btinternet.com>...
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.


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

--
Richard Heathfield : bi****@eton.powernet.co.uk
"Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
K&R answers, C books, etc: http://users.powernet.co.uk/eton
Nov 14 '05 #27

P: n/a
Sidney Cadot wrote:
Allin Cottrell wrote:
Sidney Cadot wrote:
Plauger2 (I think) goes further, and bemoans the fact that
automatic conversion from (void *) to (whatever *) was ever
accepted into standard C. To Plauger2 (who may not correspond
to the real P.J. Plauger, but apparently does correspond to
E.R. Tisdale)


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.

--
Allin Cottrell
Department of Economics
Wake Forest University, NC
Nov 14 '05 #28

P: n/a
Allin Cottrell wrote:
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 wrote:
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++.


Nov 14 '05 #29

P: n/a
In article <ln************@nuthaus.mib.org> Keith Thompson <ks***@mib.org> writes:
....
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.
--
dik t. winter, cwi, kruislaan 413, 1098 sj amsterdam, nederland, +31205924131
home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/
Nov 14 '05 #30

P: n/a
"E. Robert Tisdale" <E.**************@jpl.nasa.gov> writes:
[...]
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 wrote:
> 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
<bw*******************@nwrddc02.gnilink.net>:
] 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.)

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://www.sdsc.edu/~kst>
Schroedinger does Shakespeare: "To be *and* not to be"
Nov 14 '05 #31

P: n/a
Chris Torek wrote:
In article <news:40******@news.wineasy.se>
Johan Lindh <jo***@linkdata.getridofthis.se> writes:
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>.


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.
Nov 14 '05 #32

P: n/a
Chris Torek wrote:
In article <news:40******@news.wineasy.se>
Johan Lindh <jo***@linkdata.getridofthis.se> writes:
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>.


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
Nov 14 '05 #33

P: n/a
In article <40******@news.wineasy.se> Johan Lindh <jo***@linkdata.getridofthis.se> writes:
....
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?


"Basic Combined Programming Language"
--
dik t. winter, cwi, kruislaan 413, 1098 sj amsterdam, nederland, +31205924131
home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/
Nov 14 '05 #34

P: n/a
On Fri, 06 Feb 2004 15:27:19 -0800, E. Robert Tisdale wrote:
Richard Heathfield wrote:
If you must compare, at least compare to good code:

int *x = malloc(sizeof *x * n);


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.

Nov 14 '05 #35

P: n/a
Kelsey Bjarnason wrote:
E. Robert Tisdale wrote:
Richard Heathfield wrote:
If you must compare, at least compare to good code:

int *x = malloc(sizeof *x * n);
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:


You probably meant "Appeal to Authority".

http://www.don-lindsay-archive.org/s...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.

Nov 14 '05 #36

P: n/a
In <c0********@enews1.newsguy.com> Chris Torek <no****@torek.net> writes:
In article <ln************@nuthaus.mib.org>
Keith Thompson <ks***@mib.org> writes:
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.


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
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 14 '05 #37

This discussion thread is closed

Replies have been disabled for this discussion.