malloc

Write here if you have problems with your C source code

Moderator: Board moderators

Post Reply
User avatar
Roby
Experienced poster
Posts: 101
Joined: Wed May 04, 2005 4:33 pm
Location: Tangerang, Banten, Indonesia
Contact:

malloc

Post by Roby » Sat Mar 25, 2006 7:52 am

Does anyone know the effect and the difference between these:

Code: Select all

curr = ( struct data * ) malloc ( sizeof( struct data ) );
and

Code: Select all

curr = malloc ( sizeof( struct data ) );
Thanx...

kryptolus
New poster
Posts: 16
Joined: Sun Mar 19, 2006 9:36 am
Location: New York

Re: malloc

Post by kryptolus » Sat Mar 25, 2006 8:09 am

Roby wrote:Does anyone know the effect and the difference between these:

Code: Select all

curr = ( struct data * ) malloc ( sizeof( struct data ) );
and

Code: Select all

curr = malloc ( sizeof( struct data ) );
Thanx...
malloc() returns type void * so the result must be type cast if curr is of a different type. the only affect is to make the compiler happy. there is no runtime difference

User avatar
Roby
Experienced poster
Posts: 101
Joined: Wed May 04, 2005 4:33 pm
Location: Tangerang, Banten, Indonesia
Contact:

Post by Roby » Sun Mar 26, 2006 6:18 am

Make the compiler "happy"? So, it's permitted if I write this:

Code: Select all

curr = malloc ( sizeof( struct data ) )
instead of the other one, isn't it? Can somebody give me more technical reason what's the effect of doing this? Sorry, just wanna know more...

Thanx...

kryptolus
New poster
Posts: 16
Joined: Sun Mar 19, 2006 9:36 am
Location: New York

Post by kryptolus » Mon Mar 27, 2006 3:49 am

Roby wrote:Make the compiler "happy"? So, it's permitted if I write this:

Code: Select all

curr = malloc ( sizeof( struct data ) )
instead of the other one, isn't it? Can somebody give me more technical reason what's the effect of doing this? Sorry, just wanna know more...

Thanx...
Some compilers will give you a warning and some compilers will give you an error. It's a matter of type safety. The compiler checks to make sure that the return type of a function is compatible with the context it's used in. For your example, it will check if void * is compatible with the type of 'curr'. If the type of curr is 'void *', the compiler will let it go. What if 'curr' is a pointer to a different type? The compiler doesn't know if the conversion is legal. That's why it will give you a warning. By adding a manual type cast, you are telling the compiler that the conversion is safe. There really isn't any more depth to this.

User avatar
Roby
Experienced poster
Posts: 101
Joined: Wed May 04, 2005 4:33 pm
Location: Tangerang, Banten, Indonesia
Contact:

Post by Roby » Mon Mar 27, 2006 6:07 am

Thanx, kryptolus, for your explanation :)

sumankar
A great helper
Posts: 286
Joined: Tue Mar 25, 2003 8:36 am
Location: calcutta
Contact:

Post by sumankar » Mon Mar 27, 2006 10:44 am

kryptolus wrote:Some compilers will give you a warning and some compilers will give you an error...
That is not true. If it's a C compiler that you have in mind, you are wrong.
You don't need the cast. Simple. Try it out. In fact, a better way to
write that would be:

Code: Select all

 struct mystruct *pstrct = malloc( sizeof *pstrct ); 
The C Standard says:
A pointer to void may be converted to or from a pointer to any incomplete or object
type. A pointer to any incomplete or object type may be converted to a pointer to void
and back again; the result shall compare equal to the original pointer.


There are very very few cases when you need the cast, one such is
when you want the code to compile both as C and C++ and which is
not very often.

And oh! before I forget, the cast shuts the compiler up, so that
even if you did not do a

Code: Select all

#include <stdlib.h> 
the
compiler will not complain. And there you've masked an error.
That directive is required because you need to have a prototype
in scope for malloc() and friends. What you have then is Undefined
Behavior.

And finally if you cast to the wrong type ...

kryptolus
New poster
Posts: 16
Joined: Sun Mar 19, 2006 9:36 am
Location: New York

Post by kryptolus » Mon Mar 27, 2006 1:36 pm

I guess I didn't know as much as I thought I did.
Thanks for the correction. :)

sumankar
A great helper
Posts: 286
Joined: Tue Mar 25, 2003 8:36 am
Location: calcutta
Contact:

Post by sumankar » Mon Mar 27, 2006 3:59 pm

kryptolus wrote:I guess I didn't know as much as I thought I did.
Thanks for the correction. :)
It happens to all of us all the time :D

User avatar
Roby
Experienced poster
Posts: 101
Joined: Wed May 04, 2005 4:33 pm
Location: Tangerang, Banten, Indonesia
Contact:

Post by Roby » Tue Mar 28, 2006 2:42 am

There are very very few cases when you need the cast, one such is
when you want the code to compile both as C and C++ and which is
not very often.
Can you give me the example? I really confused about it. Thanx in advance. :)

sumankar
A great helper
Posts: 286
Joined: Tue Mar 25, 2003 8:36 am
Location: calcutta
Contact:

Post by sumankar » Tue Mar 28, 2006 5:19 am

That was the example I had in mind.

Code: Select all

#include <stdlib.h>
int main(void)
{
     struct mystrct *pstrct = malloc( sizeof *pstrct );
     return 0;
}
will compile without problems on a C compiler. C++ does not allow implicit
conversion from void* to any other type. So if you wanted this to get compiled
on a C++ compiler as well you'd have to write something like:

Code: Select all

#include <stdlib.h> // yes, I know about <cstdlib> :)
int main(void)
{
     struct mystrct *pstrct = (struct mystrct *)malloc( sizeof *pstrct );
     return 0;
}
The C committee is to be blamed for this subtle difference in dialect
of the two languages which otherwise has a broad common ground
(this particular usage of void * was borrowed from C++.)

However, have no prejudice and keep in mind it is not required in C but it
is allowed :) As for C++, the need goes away when you use new
instead. Here's a bit more story:

All examples in K&R2 are valid C++, with the same semantics as in C.

The authors have publicly admitted that this was a mistake on their
part :-) This is from the K&R2 errata:

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.

User avatar
Roby
Experienced poster
Posts: 101
Joined: Wed May 04, 2005 4:33 pm
Location: Tangerang, Banten, Indonesia
Contact:

Post by Roby » Wed Mar 29, 2006 5:50 am

Thanx Sumankar for the explanation, it's really-really very clear :)

I just want to know if there is:

Code: Select all

#include <cstdlib>
Coz I've just seen it in this forum (sorry for my lack knowledge). And what's the difference with this:

Code: Select all

#include <stdlib.h>
Is it same?

And one question again, which one should I use: malloc.h, stdlib.h, or alloc.h? Those three header files all contains malloc function and I usually use malloc.h for my program.

Thanx in advance :)

sumankar
A great helper
Posts: 286
Joined: Tue Mar 25, 2003 8:36 am
Location: calcutta
Contact:

Post by sumankar » Wed Mar 29, 2006 7:39 am

What I've gathered over the years regarding this is:
[0] There was no consensus on which extension to use -- .h, .hpp, .h++ etc
-- whence the idea to drop them.
[1] A compiler implementor is free to make a header's declaration
available in any form it wishes -- not only files. Hence the decision to drop
the '.h' that is so closely tied to the idea of a file on disk.
[2] When namespaces arrived, the C++ committee decided to wrap most
of the standard C library stuff in the 'std' namespace and rename the
headers by prepending a 'c' and dropping the '.h' suffix. The effect is
now to get at library features you use:

Code: Select all

#include <cstdio> 
int main(void) { std::printf("Hello, world!\n"); }
Further the committee deprecated the old-style-'.h' headers. Most of the
time what happens is cstdio includes stdio.h and puts the identifiers
from global namespace to namespace std.

User avatar
Roby
Experienced poster
Posts: 101
Joined: Wed May 04, 2005 4:33 pm
Location: Tangerang, Banten, Indonesia
Contact:

Post by Roby » Wed Mar 29, 2006 8:22 am

Thanx Sumankar for your clear explanation :D I'm clear now

Post Reply

Return to “C”