Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > (FAQ details:) malloc(), void * and casts

Reply
Thread Tools

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

 
 
Peter Nilsson
Guest
Posts: n/a
 
      11-14-2007
Mark Bluemel <(E-Mail Removed)> wrote:
> Asbjørn Sæbø wrote:
> > Mark Bluemel <(E-Mail Removed)> writes:
> > > 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.

> > and should not elicit any warnings ("diagnostics"?)
> > from the compiler?


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.

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

--
Peter

 
Reply With Quote
 
 
 
 
Lorenzo Villari
Guest
Posts: n/a
 
      11-19-2007
"Paul Hsieh" <(E-Mail Removed)> ha scritto nel messaggio
news:(E-Mail Removed) oups.com...

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



 
Reply With Quote
 
 
 
 
Julienne Walker
Guest
Posts: n/a
 
      11-19-2007
On Nov 13, 8:46 pm, Paul Hsieh <(E-Mail Removed)> wrote:
> On Nov 13, 5:14 am, Asbjørn Sæbø <(E-Mail Removed)> wrote:
>
> > 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.


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.

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


...


-Jul
 
Reply With Quote
 
Paul Hsieh
Guest
Posts: n/a
 
      11-19-2007
On Nov 19, 7:38 am, "Lorenzo Villari" <(E-Mail Removed)> wrote:
> "Paul Hsieh" <(E-Mail Removed)> ha scritto nel
> > 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...


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

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


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

--
Paul Hsieh
http://www.pobox.com/~qed/
http://bstring.sf.net/
 
Reply With Quote
 
Paul Hsieh
Guest
Posts: n/a
 
      11-19-2007
On Nov 19, 10:49 am, Julienne Walker <(E-Mail Removed)> wrote:
> On Nov 13, 8:46 pm, Paul Hsieh <(E-Mail Removed)> wrote:
> > On Nov 13, 5:14 am, Asbjørn Sæbø <(E-Mail Removed)> wrote:

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

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

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


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.

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


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.

--
Paul Hsieh
http://www.pobox.com/~qed/
http://bstring.sf.net/
 
Reply With Quote
 
CJ
Guest
Posts: n/a
 
      11-19-2007
On 13 Nov 2007 at 13:20, Mark Bluemel wrote:
> Asbjørn Sæbø wrote:
>
>> 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.


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.

 
Reply With Quote
 
Ian Collins
Guest
Posts: n/a
 
      11-19-2007
CJ wrote:
> On 13 Nov 2007 at 13:20, Mark Bluemel wrote:


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

That's a very rare corner case. Such libraries probably require
malloc.h as well.

--
Ian Collins.
 
Reply With Quote
 
Flash Gordon
Guest
Posts: n/a
 
      11-19-2007
Julienne Walker wrote, On 19/11/07 18:49:
> On Nov 13, 8:46 pm, Paul Hsieh <(E-Mail Removed)> wrote:
>> On Nov 13, 5:14 am, Asbjørn Sæbø <(E-Mail Removed)> wrote:
>>
>>> 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.

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

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


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.

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


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.

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


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.
--
Flash Gordon
 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      11-19-2007
Paul Hsieh wrote:
> On Nov 19, 7:38 am, "Lorenzo Villari" <(E-Mail Removed)> wrote:
>> "Paul Hsieh" <(E-Mail Removed)> ha scritto nel
>>> 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...

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

--
Keith Thompson (The_Other_Keith) <(E-Mail Removed)>
Looking for software development work in the San Diego area.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      11-19-2007
CJ wrote:
> On 13 Nov 2007 at 13:20, Mark Bluemel wrote:
>> Asbjørn Sæbø wrote:
>>
>>> 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.


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>?

--
Keith Thompson (The_Other_Keith) <(E-Mail Removed)>
Looking for software development work in the San Diego area.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
What is the difference between void proba(); and void proba(void); ??? PencoOdStip@gmail.com C++ 1 05-23-2007 07:12 PM
Are implicit casts to void*& illegal? Ray Gardener C++ 3 04-19-2006 08:55 AM
what is the difference, void func(void) and void fucn() noblesantosh@yahoo.com C Programming 5 07-22-2005 04:38 PM
"void Method()" vs "void Method(void)" Ollej Reemt C++ 7 04-22-2005 03:47 AM
`void **' revisited: void *pop(void **root) Stig Brautaset C Programming 15 10-28-2003 09:03 AM



Advertisments