malloc and pointer casting

M

Mirko

Hello, I'm new to this list and to Usenet in general,
so please forgive (and advice) me, if I do something wrong.

Anyway.

I am a bit confused, because I always thought one
_should_ explicitly cast the void* pointer returned by malloc.
Now I read postings saying that this is dangerous.

Could somebody please clearify this?

Thanks
Mirko
 
E

Emmanuel Delahaye

Mirko wrote on 31/08/05 :
Hello, I'm new to this list and to Usenet in general,
so please forgive (and advice) me, if I do something wrong.

I am a bit confused, because I always thought one
_should_ explicitly cast the void* pointer returned by malloc.

You can, but it's just another waste of time. Please read the FAQ.

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

I once asked an expert COBOL programmer, how to
declare local variables in COBOL, the reply was:
"what is a local variable?"
 
M

Mike Wahler

Mirko said:
Hello, I'm new to this list and to Usenet in general,
so please forgive (and advice) me, if I do something wrong.

Anyway.

I am a bit confused, because I always thought one
_should_ explicitly cast the void* pointer returned by malloc.

Why did you think that? If you learned it from a book,
please tell us the title and author so we can warn
others about it.
Now I read postings saying that this is dangerous.

Could somebody please clearify this?

Casting the return value from 'malloc()' can mask errors
(e.g. failure to provide its prototype via #including
<stdlib.h>). In C89, calling a function without a
prototype will cause a compiler to assume its return
type is 'int'. So the returned pointer would be
treated as type 'int', often corrupting its value.
C99 makes this issue moot since it requires a prototype
be in scope for any function called. However C99 is
not in very widespread use yet, so this is still a
very real issue.

A 'void*' pointer can be implicitly converted to any
other pointer type without any cast.

IOW do things like so:

#include <stdlib.h>

int main()
{
int *p = malloc(sizeof *p * 100); /* 100 is arbitrary
number for this example */

if(p)
{
/* do something with 'p' */

free(p);
}
else
/* memory allocation failed, take corrective action */

return 0;
}

Note that I also addressed another common mishandling of 'malloc()':
failure to check its return value to see if it succeeded or not.


comp.lang.c Frequently Asked Questions:
http://www.eskimo.com/~scs/C-faq/faq.html

-Mike
 
K

Kenneth Brody

Mike said:
"Mirko" <[email protected]> wrote in message
[... casting the return from malloc() ...]
Casting the return value from 'malloc()' can mask errors
(e.g. failure to provide its prototype via #including
<stdlib.h>). In C89, calling a function without a
prototype will cause a compiler to assume its return
type is 'int'. So the returned pointer would be
treated as type 'int', often corrupting its value.
[...]

To clarify this point...

On some systems, sizeof(int) < sizeof(void*), meaning that, at best,
the upper bits of the return value are lost, resulting in an invalid
pointer. (For example, a 16-bit DOS system with 32-bit FAR pointers.)

Worse, some systems return pointers differently than integers. For
example, I've seen a CPU with two sets of registers -- one for data,
one for addresses -- and the return value from functions was stored
in the appropriate register. So, malloc() returns the pointer in the
A0 register, while your code, thinking that malloc() returns an int,
reads the D0 register for the value.

Casting the return from malloc() would hide any warnings.


--
+-------------------------+--------------------+-----------------------------+
| Kenneth J. Brody | www.hvcomputer.com | |
| kenbrody/at\spamcop.net | www.fptech.com | #include <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------------+
Don't e-mail me at: <mailto:[email protected]>
 
C

Christian Kandeler

Mike said:
Why did you think that? If you learned it from a book,
please tell us the title and author so we can warn
others about it.

Brian W. Kernighan, Dennis M. Ritchie: The C Programming Language (2nd
Edition).


Christian
 
J

John Bode

Mirko said:
Hello, I'm new to this list and to Usenet in general,
so please forgive (and advice) me, if I do something wrong.

Anyway.

I am a bit confused, because I always thought one
_should_ explicitly cast the void* pointer returned by malloc.
Now I read postings saying that this is dangerous.

Could somebody please clearify this?

Thanks
Mirko

You've already gotten the correct answer, I just want to add a little
historical context.

Prior to C89, malloc() returned a char* instead of a void*, so a cast
*was* required if the target wasn't a char*. So anyone who's been
using C since before C89 is likely to still use the cast out of habit,
even though it's no longer necessary.

Also, anyone who goes back and forth between C++ and C is likely to use
the cast, since C++ *doesn't* allow implicit conversions between void*
and any other pointer type (but if you're writing C++, you shouldn't be
using malloc() anyway).
 
M

Mirko

Thanks to all who have answered, got exactly the information I was
after.

Perhaps one should add some lines to the FAQ, since it is not very
informativ (presice) on that topic.

Sorry, for this, to take so long, but I don't have an own internet
access,
so I can't read news regulary (in fact, it can take one or two weeks
for
me to respond).

Thanks again

Greetings
Mikro
 
M

Mirko

Why did you think that? If you learned it from a book,
please tell us the title and author so we can warn
others about it.
Uhm, just too many... (mainly german, so called From-Beginner-to-Expert
books).

C99 makes this issue moot since it requires a prototype
be in scope for any function called.
Perhaps I'm mixing up different meanings of "scope", but if I
understand
you correctly, then it is forbidden in C99 to do something like this
(IMHO bad style anyway):

foo.c
/* C99 would _require_ this; prior, we just get a warning. */
/* int foo(void); */

int main(void)
{
/* Wired, but C99 wouldn't complain, since prototype would be in
scope. */
/* int foo(void); */

return foo(); /* error: no prototype in scope */
}

int foo(void)
{
return 0;
}
 
E

E. Robert Tisdale

Mirko said:
I am a bit confused because I always thought [that]
one _should_ explicitly cast the void* pointer returned by malloc.

That's correct.
Now I read postings saying that this is dangerous.
FUD

http://wombat.doc.ic.ac.uk/foldoc/

Could somebody please clarify this?

C++ requires the explicit cast but C does not.
Try to write code that will compile as either C or C++.
> cat main.c
#include <stdlib.h>

int main(int argc, char* argv[]) {
const
size_t n = 100; // arbitrary size for this example
int* p = (int*)malloc(n*sizeof(int));

if (NULL == p) { // Memory allocation failed.
// Take corrective action.
}
else {
// Do something with 'p'.
}

free(p);
return 0;
}
> gcc -x c -Wall -std=c99 -pedantic -o main main.c
> gcc -x c++ -Wall -ansi -pedantic -o main main.c

Don't write C code that C++ cannot accept.
C++ will eventually replace C
and you will either need to re-write your code or throw it away.
 
J

John Bode

E. Robert Tisdale said:
Mirko said:
I am a bit confused because I always thought [that]
one _should_ explicitly cast the void* pointer returned by malloc.

That's correct.

In C++, yes. In K&R C, yes. In C89 and later, *no*.

Put another way, it's just as correct as casting the result of "new".

Snipping the rest.
 
M

Martin Ambuhl

John said:
E. Robert Tisdale said:
Mirko wrote:

I am a bit confused because I always thought [that]
one _should_ explicitly cast the void* pointer returned by malloc.

That's correct.

In C++, yes. In K&R C, yes. In C89 and later, *no*.

BZZT! In K&R C there is no such thing as a void*, so it cannot be true
that in K&R C one should explicitly cast the void* pointer returned by
malloc. Casting the char* returned by a K&R C library's malloc would be
a good idea, though.
 
J

John Bode

Martin said:
John said:
E. Robert Tisdale said:
Mirko wrote:


I am a bit confused because I always thought [that]
one _should_ explicitly cast the void* pointer returned by malloc.

That's correct.

In C++, yes. In K&R C, yes. In C89 and later, *no*.

BZZT! In K&R C there is no such thing as a void*, so it cannot be true
that in K&R C one should explicitly cast the void* pointer returned by
malloc. Casting the char* returned by a K&R C library's malloc would be
a good idea, though.

Brain fart -- I misread "the void* pointer returned by malloc" as "the
value returned by malloc".

It's been a long week already, and this just made it longer.
 
K

Keith Thompson

E. Robert Tisdale said:
Mirko said:
I am a bit confused because I always thought [that]
one _should_ explicitly cast the void* pointer returned by malloc.

That's correct.

No, it isn't.
C++ requires the explicit cast but C does not.
Try to write code that will compile as either C or C++.

Write in C, or write in C++. A very few developers have a legitimate
need to write code that's compatible with both. If you have such a
need, chances are you're P.J. Plauger, and you don't need advice from
me.
Don't write C code that C++ cannot accept.
C++ will eventually replace C
and you will either need to re-write your code or throw it away.

There is no reason to believe that C++ will replace C.
 
D

Dave Thompson

Mike Wahler wrote:

Actually C99 requires a declaration but not necessarily a prototype. A
prototype in C is a specific kind of declaration or definition, that
specifies the types (at least) of the parameters in the parentheses
indicating that it is a function, although many people misuse the term
to mean any declaration of a function, especially "published".
Perhaps I'm mixing up different meanings of "scope", but if I
understand
you correctly, then it is forbidden in C99 to do something like this
(IMHO bad style anyway):

foo.c
/* C99 would _require_ this; prior, we just get a warning. */
/* int foo(void); */

int main(void)
{
/* Wired, but C99 wouldn't complain, since prototype would be in
scope. */
/* int foo(void); */

return foo(); /* error: no prototype in scope */
}
<snip>

Sort of. Let's review:

int foo (void); is a prototype declaration of a function with no
arguments. int foo (); is a declaration but not a prototype.
Prototypes are better because they allow more error checking by the
compiler and appropriate automatic conversion of arguments (for
functions that take arguments, of course) but they are not required,
not even in C99. (They are, effectively, in C++.)

Before C99, you can declare a function at file scope a.k.a. top level
and it applies to the whole rest of the file (translation unit) unless
shadowed, or you can declare it within a function body or other block
and it applies only within that block. Or, if you call a named
function directly and it you haven't declared it either place, the
compiler assumes an implicit declaration like int foo() i.e. returning
int and accepting unspecified fixed default-promoted arguments.

It is considered poor style to put function declarations locally in a
function/block, because that's not where people expect to see them or
find them when looking, and it allows the coder to accidentally or
intentionally have inconsistent declarations e.g. char * foo (int) in
one place and void foo (int, char *) in another, which is wrong and
often badly wrong, without the compiler detecting. But it is legal.

C99 removes the last option, implicit declaration. You can declare,
prototype or not, at file scope or local scope. But you must declare.

- David.Thompson1 at worldnet.att.net
 

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

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,022
Latest member
MaybelleMa

Latest Threads

Top