regarding free function in c library

P

paolo

Hi Everyone,

It is known that function free() of c library expects parameter of
type void* and when we invoke them with pointers to any type, compiler
automatically performs the typecast, can anyone let me know as to why
pointers are typecasted to void* in many places before performing
operation on them?
 
L

Lew Pitcher

**BUMP**

Anyone is in this room ???

You should be aware that usenet is a /very/ asynchronous process; it takes
appreciable time for posts to propogate from server to server (sometimes
days), and /even more/ time for people to pull posts down from their server
and read them. Often, the response will involve a lot of detail, which
takes time to collect and transcribe.

In other words, be patient, little one.


The C standard requires void pointers (that is, pointer to void) in a number
of places where the logic requires that such pointer refer to one of a
number of different types, depending on other indicators. (the argument
pointers passed to printf() and scanf() come to mind here). When prototyped
functions accept void pointers, the compiler converts from typed pointer to
void pointer as part of the function call sequence. Similarly, when
prototyped functions return a void pointer, the compiler converts to typed
pointer as part of the function return sequence.

AFAIK, there is no requirement in the standard that the programmer
explicitly cast typed pointers to void pointers. I may be wrong here, and I
expect those with better knowledge of the standard to correct me.

However, other languages (read C++) /do/ have requirements for explicit
casts of typed pointers to void pointers. Programmers used to working with
those languages often mistakenly cast pointers to void* in their C code.

Perhaps, this is the behaviour that you have noticed.

HTH
 
L

Lew Pitcher

On December 17, 2011 17:30, in comp.lang.c, (e-mail address removed)
wrote: [snip][snip]
Similarly, when prototyped functions return a void pointer, the compiler
converts to typed pointer as part of the function return sequence.

I should correct this; the conversion happens on assignment, not on function
return.

Thus, in
double *mynumber;
mynumber = malloc(sizeof *mynumber);
the conversion of the void pointer (void *) returned by malloc() happens
when the value of that pointer is assigned to the double pointer (double *)
mynumber.
 
K

Keith Thompson

paolo said:
**BUMP**

Anyone is in this room ???
[snip]

This is not a "room". This is Usenet. Messages do not appear
immediately because there is no single server; rather, messages are
forwarded across a network of servers. It's not reasonable to expect to
get answers within 10 minutes of posting. If you don't get a response
within a couple of days, it *might* be time to start being concerned.

Another note: top-posting is discouraged. Suggested reading:
http://www.caliburn.nl/topposting.html
http://www.cpax.org.uk/prg/writings/topposting.php
 
K

Keith Thompson

paolo said:
It is known that function free() of c library expects parameter of
type void* and when we invoke them with pointers to any type, compiler
automatically performs the typecast, can anyone let me know as to why
pointers are typecasted to void* in many places before performing
operation on them?

It's a conversion, not a "typecast". A cast is an explicit
operator, consisting of a type name in parentheses, that specifies a
conversion. A conversion can be either explicit (by means of a cast)
or implicit. ("Typecasting" is something that happens to actors.)

The reason for the implicit conversion is that, as you say, free()
takes an argument of type void*. It cannot operate directly on,
for example, a pointer of type int*. The language supports implicit
conversions from most pointer types to void* (and vice versa) for
the sake of convenience. The language additionally guarantees
that converting a pointer to void* and then back again yields
the original value.

(None of this applies to pointer-to-function types.)

void* is effectively a generic pointer type.

In the absence of the implicit conversion, you'd have to do it
explicitly:

int *ptr = (int*)malloc(sizeof *ptr);
...
free((void*)ptr);

as opposed to the simpler:

int *ptr = malloc(sizeof *ptr);
...
free(ptr);

There's no real type safety issue in these particular cases, so the
increased convenience is worthwhile.
 
B

BartC

Keith Thompson said:
It's a conversion, not a "typecast". A cast is an explicit
operator, consisting of a type name in parentheses, that specifies a
conversion. A conversion can be either explicit (by means of a cast)
or implicit. ("Typecasting" is something that happens to actors.)

"In computer science, type conversion, typecasting, and coercion are
different ways of, implicitly or explicitly, changing an entity of one data
type into another."

(http://en.wikipedia.org/wiki/Type_conversion)

It may not appear in the C standard, but since this isn't a showbiz forum,
everyone knows what is meant.
 
E

Eric Sosman

"In computer science, type conversion, typecasting, and coercion are
different ways of, implicitly or explicitly, changing an entity of one
data type into another."

(http://en.wikipedia.org/wiki/Type_conversion)

It may not appear in the C standard, but since this isn't a showbiz
forum, everyone knows what is meant.

"The free encyclopedia that anyone can edit," whether he knows
anything or not.
 
J

James Kuyper

On 12/17/2011 05:47 PM, Lew Pitcher wrote:
....
AFAIK, there is no requirement in the standard that the programmer
explicitly cast typed pointers to void pointers.

That's correct; the conversion is implicit in an assignment expression,
and therefore also when a pointer is passed as one of the arguments
listed in a function prototype that is in scope at the point where the
function is called, and also in the expression part of a return
statement: in both cases the behavior is defined by cross-referencing
the rule for simple assignment.
 
E

Eric Sosman

[...]
AFAIK, there is no requirement in the standard that the programmer
explicitly cast typed pointers to void pointers. I may be wrong here, and I
expect those with better knowledge of the standard to correct me.

A few corner cases exist, when passing arguments to variadic
functions or to functions without prototypes:

void func(ptr)
void* ptr;
{ ... }

int i, *p = &i;

printf ("p = %p\n", p); // RONG
printf ("p = %p\n", (void*)p); // Right

func(p); // RONG
func((void*)p); // Right

On a related note, observe that the NULL macro may expand to
a plain `0' without pointer-y accoutrements. So when passing NULL
to a variadic or prototypeless function that expects void* value
(or anything* values, for that matter), you need to cast NULL.
 
P

paolo

OK

Will you think this to be because a limitation of C ? In true there ought
be overloaded functions
free(int*);
free(double*);
etc etc,

however....

C not supports overloading so this "kluge" of conversion is needed for
what you say "increased convenience"
 
E

Eric Sosman


Still not quite grasping the message about top-posting, eh?
Will you think this to be because a limitation of C ? In true there ought
be overloaded functions
free(int*);
free(double*);
etc etc,

Try this exercise: Write out the "etc etc" in its entirety,
and count how many overloadings of free() you'll need. (Hint:
the number is countable, but if you ever finish the count you'll
have overlooked more versions than you've counted.)
 
L

Lauri Alanko

On a related note, observe that the NULL macro may expand to
a plain `0' without pointer-y accoutrements. So when passing NULL
to a variadic or prototypeless function that expects void* value
(or anything* values, for that matter), you need to cast NULL.

This also applies to casting to intptr_t. Is there any rationale why
plain 0 is allowed for NULL? I'm feeling tempted to define my own
macro for (void*)0 just to avoid the above pitfalls...


Lauri
 
E

Eric Sosman

This also applies to casting to intptr_t.

Not quite sure how that bears on the question of casting typed
pointers to void pointers, since intptr_t is neither. But anyway ...
Is there any rationale why
plain 0 is allowed for NULL?

Quoth the, er, um, Rationale:

NULL can be defined as any null pointer constant. Thus existing
code can retain definitions of NULL as 0 or 0L, but an
implementation may also choose to define it as (void*)0. This
latter form of definition is convenient on architectures where
sizeof(void*) does not equal the size of any integer type.

But it then goes on to say

It has never been wise to use NULL in place of an arbitrary
pointer as a function argument, however, since pointers to
different types need not be the same size.

From this, my guess is that prior to the Standard-ization of NULL
there were plenty of systems that provided their own NULL definitions.
Those definitions would not have been ((void*)0), since void* was not
part of the language as described in K&R, and many compilers would not
have been able to process it. So those implementations defined their
own NULL's as 0 or some close variant, and the Committee felt it would
be unwise to invalidate them and the programs that had grown up with
them. As the Rationale says elsewhere, "Existing code is important,
existing implementations are not."
I'm feeling tempted to define my own
macro for (void*)0 just to avoid the above pitfalls...

There's a fuzzy line between enhancement and obfuscation. If
you run across a line like

func(13.6, &a, &b, (void*)NULL);

you have to ask yourself whether it's more or less readable than

func(13.6, &a, &b, ALANKO);

Even then, you might find yourself needing to write

func(14.6, &a, &b, (struct goombah*)ALANKO);

.... and it doesn't seem to me you've gained a whole lot.
 
L

Lew Pitcher

OK

Will you think this to be because a limitation of C ? In true there ought
be overloaded functions
free(int*);
free(double*);
etc etc,

Hmmmm..... Assuming

how would your proposed change to the standard handle

struct {
int number;
float percent[8];
double dpercent[4];
char string[64];
} *myStruct;

myStruct = malloc(sizeof *myStruct);

how would your suggestion for overloaded functions handle the freeing up of
the memory allocated to myStruct ?

In C, this is
free(myStruct);
but, with the /requirement/ of overloading, you would have to code a
special, overloaded version of free() for each application-defined
structure pointer. /I/ don't think that such overloading can be adequately
defined by the standard (it would have to enumerate each possible type of
pointer, and that is an open-ended set), and it seems worse to me to force
coders to write a specially-overloaded free() than it is just to hand
free() a pointer.
however....

C not supports overloading so this "kluge" of conversion is needed for
what you say "increased convenience"

One man's kludge is another mans optimization.

In this case, I'd call overloading a kludge that gives a tight-typed
language (C++) capabilities similar to a loosly-typed language (C).
 
K

Keith Thompson

Eric Sosman said:
Still not quite grasping the message about top-posting, eh?


Try this exercise: Write out the "etc etc" in its entirety,
and count how many overloadings of free() you'll need. (Hint:
the number is countable, but if you ever finish the count you'll
have overlooked more versions than you've counted.)

The language *could* have handled this by making free an operator
rather than a function.

Early versions of C didn't have a standard memory allocation system;
K&R1, published in 1978, shows sample alloc() and free() functions,
but doesn't show any such things in the standard library (if I
recall correctly).

malloc() and free() were added to the standard library after
the language had been fairly well established. Initially, they
operated on char* pointers, since void* hadn't been invented yet.
When the ANSI C standard was published in 1989, it added void* to
the language along with the implicit conversion rules. This allowed
existing code that used malloc() and free() to continue to be used
(with the addition of "#include <stdlib.h>").

Quite possibly if the language were being designed from scratch
today, it would have been done differently. (C++, with less concern
for backward compatilibity, has "new" and "delete" operators -- but
those are also necessary because of the need to invoke constructors
and destructors, something C doesn't have.)
 
N

Nick Keighley

     Still not quite grasping the message about top-posting, eh?


     Try this exercise: Write out the "etc etc" in its entirety,
and count how many overloadings of free() you'll need.  (Hint:
the number is countable,

"countable" is mathematician-speak for "not practically countable".
We're looking at numbers where even counting the zeros is tough.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,764
Messages
2,569,566
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top