struct my_struct *p = (struct my_struct *)malloc(sizeof(struct my_struct));

D

Dan Pop

Let's correct it : void * may be converted to a pointer to any incomplete or
object type. As well, void* may be converted from a pointer to any
incomplete or object type. This is what I read in C99 §6.3.2.3.
You were probably hurt by seeing "void* IS ... converted".

I was hurt by not seeing *anywhere* in 6.3.2.3 that the conversion
doesn't require a cast. I am still hurt... ;-)

Dan
 
I

Irrwahn Grausewitz

Chris Fogelklou said:
"Régis Troadec" <[email protected]> wrote in message

Do you know if this was also a standard in C89/C90?

intptr_t and uintptr_t are new features of C99, as is everything else
in stdint.h. They're optional features, BTW.
If so, it would
strengthen my argument since the recent response was that "GCC-derived
compilers don't fully support C99 yet." Not sure if it's true... Any
thoughts?

Have a look at http://gcc.gnu.org/c99status.html.
Not sure what she meant with arithmetic operations... you don't normally do
arithmetic on pointers,

Ah, but you do, e.g. every time you use array subscription, 'walk' an
array by incrementing a pointer, add the result of the offsetof macro
to a pointer, subtract two pointers from each other, etc.
but if you did, I guess you could just cast to an
integral type of the correct size, correct?

Alas, there's no guarantee that you can cast back the result of your
operations and get a valid pointer value, so it's effectively pretty
useless. If you want to do pointer arithmetic, well, do arithmetic
on pointers. Simple, isn't it? ;-)
The fact is I am very uncomfortable holding addresses in an integral data
type.

And you're right, because you're not supposed to know anything of
the inner structure of pointers. After all, that's why pointer types
are distinct from the other types. I wouldn't be surprised if
somebody comes up with an example for an architecture where pointer
values cannot meaningfully represented in an object of any integer
type at all.

Regards
 
C

Chris Fogelklou

Irrwahn Grausewitz said:
intptr_t and uintptr_t are new features of C99, as is everything else
in stdint.h. They're optional features, BTW.


Have a look at http://gcc.gnu.org/c99status.html.


Ah, but you do, e.g. every time you use array subscription, 'walk' an
array by incrementing a pointer, add the result of the offsetof macro
to a pointer, subtract two pointers from each other, etc.


Alas, there's no guarantee that you can cast back the result of your
operations and get a valid pointer value, so it's effectively pretty
useless. If you want to do pointer arithmetic, well, do arithmetic
on pointers. Simple, isn't it? ;-)


And you're right, because you're not supposed to know anything of
the inner structure of pointers. After all, that's why pointer types
are distinct from the other types. I wouldn't be surprised if
somebody comes up with an example for an architecture where pointer
values cannot meaningfully represented in an object of any integer
type at all.
Great, thanks Irrwahn.

I guess my one unanswered question now is whether or not it was possible to
equate a void * to int * or struct my_struct * or any other type of
non-function pointer way back in C89/C90, or is that also a new addition in
C99? I can't find the C89/C90 specs anywhere on the 'net. (C99 was simple,
though.)

Eg:
int * i;
void * p;

i = malloc(sizeof(int));
*i = 5;
p = i; // would this puke under C89/C90?

Cheers,

Chris
 
I

Irrwahn Grausewitz

Chris Fogelklou said:
Great, thanks Irrwahn.

I guess my one unanswered question now is whether or not it was possible to
equate a void * to int * or struct my_struct * or any other type of
non-function pointer way back in C89/C90, or is that also a new addition in
C99?

See below.
I can't find the C89/C90 specs anywhere on the 'net. (C99 was simple,
though.)

Try one of the following URLs, AFAIK they should link to plain text
renditions of the last public draft of C89:

http://danpop.home.cern.ch/danpop/ansi.c
http://www.tkn.tu-berlin.de/~jklaue/ansic
Eg:
int * i;
void * p;

i = malloc(sizeof(int));
*i = 5;
p = i; // would this puke under C89/C90?

No, it's just fine. Just to add that this rule for simple assignment
is also valid for passing parameters to (non-variadic) prototyped
functions and returning pointer values from functions; silly example:

void *foo( void *vp )
{
int *ip = vp;
return ip;
}

int main( void )
{
int i;
int *p = foo( &i );
return 0;
}

HTH
Regards
 
C

Chris Torek

... what about this:

int my_func(void *pinst)
{
my_struct *pthis = (my_struct *)pinst; //Cast
pthis->print("Lets see what's wrong with this!");
return 0;
}

If it is OK to never cast to/from void * as was made abundantly clear last
week, then this is also OK. However, pinst could be a run-time defineable
value.

Of course, we have to assume that "my_struct" is a typedef or
#define for some structure type. (I would prefer to write out
"struct S *p" instead of "alias_for_struct_S *p" myself, which
removes the need for any such assumptions. The C style guide for
Wind River goes the other way though -- one must often conform to
externally-imposed requirements, no matter how wrong one thinks
they might be. :) )

The above is OK provided that "pinst" really points to the structure
type, and that the "print" member really points to a function that
takes a value of type "char *" or "const char *", which in turn
does not write over any of the "char"s.

The cast can be removed with no semantic change at all in C. (The
cast may not be removed in C++, but then, even more changes are
required if the above is to be compiled as Pascal or Ada, so why
would we care? :) )

I remain puzzled as to what "pinst could be a run-time defineable
value" *means*. In the above, "pinst" is a formal parameter of
type "void *", whose value is supplied at run time by the caller.
The value cannot be determined by inspection of my_func(). In
other words, the value stored in the object named "pinst" *is* a
"run-time value".
 
C

Chris Fogelklou

Chris Torek said:
Of course, we have to assume that "my_struct" is a typedef or
#define for some structure type. (I would prefer to write out
"struct S *p" instead of "alias_for_struct_S *p" myself, which
removes the need for any such assumptions. The C style guide for
Wind River goes the other way though -- one must often conform to
externally-imposed requirements, no matter how wrong one thinks
they might be. :) )

The above is OK provided that "pinst" really points to the structure
type, and that the "print" member really points to a function that
takes a value of type "char *" or "const char *", which in turn
does not write over any of the "char"s.

The cast can be removed with no semantic change at all in C. (The
cast may not be removed in C++, but then, even more changes are
required if the above is to be compiled as Pascal or Ada, so why
would we care? :) )

I remain puzzled as to what "pinst could be a run-time defineable
value" *means*. In the above, "pinst" is a formal parameter of
type "void *", whose value is supplied at run time by the caller.
The value cannot be determined by inspection of my_func(). In
other words, the value stored in the object named "pinst" *is* a
"run-time value".
Hi,

Of course, we have to assume that "my_struct" is a typedef or

Yes... my_struct is typedef'd to a type... Normally it would be called
my_struct_t in our drivers.
I remain puzzled as to what "pinst could be a run-time defineable
value" *means*.

To answer the question about pinst being run-time defineable... we are
writing embedded drivers in C using OOP and inheritance.

Most of our base-level objects have a write and read function, and other
functions on top... but write and read are always in the same place, as
they are inherited. The example I gave was a stupid example, but we do have
a "xx_printf" function that takes a parameter like pinst followed by the
usual printf parameters, creates a formatted string, and then does a "write"
to the object that pinst points to. The same "printf" function could be
printing to an LCD, a UART, SPI, you name it... the object it prints to is
more or less determined at run time.
(The
cast may not be removed in C++, but then, even more changes are
required if the above is to be compiled as Pascal or Ada

Is there really that much wrong with making code compatible with both C and
C++? If we leave the cast in there, the code could be copied and pasted
into a C++ library verbatim. Dunno... is that question heritical in this
NG?
 
C

Chris Fogelklou

<snipped my own diatribe>

Sorry... Kinda missed your point the first time around. It is a run-time
value, as opposed to something created like this:

my_struct_t *ps = malloc(sizeof(my_struct_t));

This can be figured out by the compiler at compile time, something that was
pointed out by someone else in an earlier post.
 
I

Irrwahn Grausewitz

Chris Fogelklou said:
"Chris Torek" <[email protected]> wrote:

Is there really that much wrong with making code compatible with both C and
C++? If we leave the cast in there, the code could be copied and pasted
into a C++ library verbatim. Dunno... is that question heritical in this
NG?

IIRC, conveniently being able to use the same code base for libraries
in C and C++ seems to be the only pro casting argument so far that has
survived the recurring flamew^H^H^H^H^H^H discussions in c.l.c about
the issue.

Regards
 
K

Keith Thompson

Chris Fogelklou said:
Is there really that much wrong with making code compatible with both C and
C++? If we leave the cast in there, the code could be copied and pasted
into a C++ library verbatim. Dunno... is that question heritical in this
NG?

I wouldn't say it's heretical, but it's certainly a bit touchy; we've
had interminable flamewars on the subject. Search the archives if
you're interested (and masochistic).

To summarize the general (but not unanimous) consensus of the
newsgroup (as I see it):

Casting the result of malloc() is almost never a good idea. In C90,
it can mask the error of failing to include the header that defines
the malloc() function, <stdlib.h>. (In C99, the lack of a visible
declaration triggers a diagnostic, so it's less of an issue, but there
aren't yet enough conforming C99 compilers that we can ignore C90 --
and the cast is no more useful in C99 than is is in C90.)

In the absence of a prototype for malloc(), the compiler assumes that
it's an external function returning int. Casting the result to an
object pointer type is likely to grab an int-sized chunk of data from
the pointer-sized function result, or even from somewhere else
altogether. Casts in general are frowned upon unless they're
absolutely necessary.

If you want to write C++, write C++. There's seldom any good reason
to use malloc() in C++, since the new operator is built into the
language (and it's easier to use and more type-safe). C++ programs
can call C functions, so it usually makes more sense to put your C
function in a library than to cut-and-paste it into a C++ source
program.

Having said that, there are some rare cases where there's a genuine
requirement to write code that can be compiled both as C and as C++.
P. J. Plauger is in that rare situation. If you really need to do it,
casting the result of malloc() may be the way to go. But unless you
really have such a requirement, and unless you understand the
drawbacks of using the cast, you probably shouldn't do it.

(ERT might jump into the discussion at this point. See the archives
for our previous responses to him.)
 
O

Old Wolf

I assume by 'the above' you mean:
struct my_struct *p = (struct my_struct *)malloc(sizeof(struct my_struct));

Why don't you use google or some other agent to look through past postings.
Just search for 'malloc' and 'cast'. There are several threads every week
on the topic, where it is fully explained.
<start email>
First, Casts from void * are necessary both in C and C++. This is from the
same reason you told me: otherwise, if the compiler wouldn't
know what is the size of the object which is pointed at,

You do not need to know the size of the pointed-at object, to be
able to assign a pointer. This is legal C:

#include <stdio.h>
struct foo;
void func(struct foo *p)
{
void *q = p;
printf("foo object of unknown size at %p \n", q);
}
it might get confused with arithmetic operations.

Compilers do not get confused with arithmetic operations. Maybe your
friend is thinking of arithmetic operations on void pointers, which
are undefined. This is not relevant, because you would only do arithmetic
operations on a struct pointer. A pointer to struct is not a pointer to void.
The compiler already knows how big the struct is (you even used "sizeof"
on it when calling malloc), so it can do arithmetic correctly.

If you are still unsure, do this:

#include <stdio.h>
#include <stdlib.h>
struct my_struct { /* fill in some stuff here */ };
int main(void)
{
struct my_struct *p = malloc(sizeof *p);
struct my_struct *q = p + 1;
printf("p=%p, q=%p\n", (void *)p, (void *)q);
printf("q-p = %d\n", (int)(q - p));
printf("(char*)q-(char*)p = %d\n", (int)((char*)q - (char*)p));
printf("sizeof(my_struct)=%d", (int)sizeof(struct my_struct));
return 0;
}

In fact this example would work just as well as if you had gone:
struct my_struct p[1];
proving that malloc has nothing to do with pointer arithmetic.
You can ask him where did he learned
this rule from. tell me if you want me to correspond directly with him.

The C Standard. You could also find this by reading the comp.lang.c FAQ.
(The C++ Standard is different).
Second, a possible reason to use integral types for addresses rather than
void *, is that in order to perform bitwise operations on an
address, you have to use operators of an integral type.

Bitwise operations can only be performed on integral types. If you write an
expression like (p & 1) then p is silently converted to an integral type
by the compiler.
It is non-portable to convert addresses to integral types (and may be
undefined if there is no integral type big enough to hold the pointer
value). For example, consider anything without a flat address space.

Finally, why is casting malloc's return value bad? Mainly, it suppresses
the compiler warning of malloc's prototype not being in scope (and it is
undefined behaviour to call malloc without prototype in scope, even though
it may compile correctly). This was discussed in more detail in another
thread this week. To demonstrate this, take my sample program above and
delete the "#include <stdlib.h>" line and compile it.
Also, it is harder to maintain if you change the type of what is being
allocated. That is why we prefer the form:

struct my_struct *p = malloc(sizeof *p);

because it only mentions the type-name once.
 
C

Chris Torek

Is there really that much wrong with making code compatible with both C and
C++? If we leave the cast in there, the code could be copied and pasted
into a C++ library verbatim. ...

There is nothing inherently wrong with it, but I see it as a waste of
effort in most cases.

There are quite a few subtle differences between C and C++, so that
one can write programs that are syntactically valid in both languages,
compile in both languages, yet mean something different in each
language. The problem is similar to getting Americans and Brits
to understand each other: when an American committee "tables" a
subject it is put aside to stop discussion, while the British
committee "tables" the subject to bring it up and begin discussion.

(I posted an example earlier today in which "sizeof type" changes
when the code is compiled in the alternate language. Look for
"struct scopetrick".)

More typically, good C code often fails to compile at all as C++
code (because -- among other things -- it omits casts that C++
requires); and of course good C++ code generally uses "new" instead
of malloc, or -- even better -- uses container classes.
 
C

CBFalconer

Chris said:
There is nothing inherently wrong with it, but I see it as a
waste of effort in most cases.

There are quite a few subtle differences between C and C++, so
that one can write programs that are syntactically valid in both
languages, compile in both languages, yet mean something
different in each language. The problem is similar to getting
Americans and Brits to understand each other: when an American
....

Back when I was young and in my prime there was this amiable, but
poverty stricken Yank who met this foxy Brit chick. Nature took
its course, but then she told him: "I am getting divorced, with a
big settlement. Meet me after the divorce, but meanwhile I have
to stay pristine." And she handed him an envelope and told him to
open it after the day was over.

Well, he followed instructions, and opened it and read: "Until
7/6, noon, in Trafalger Square.". Since it was January, he went
off and did other things, such as roping calves etc., and returned
to London on 7/6. He never found her again.

She meant every word of it, and she was there on 7/6, but never
found him again.

Your mission, should you care to accept it, is to explain this
paradox. Alternate timelines or universes will not be accepted.
 
S

Severian

...

Back when I was young and in my prime there was this amiable, but
poverty stricken Yank who met this foxy Brit chick. Nature took
its course, but then she told him: "I am getting divorced, with a
big settlement. Meet me after the divorce, but meanwhile I have
to stay pristine." And she handed him an envelope and told him to
open it after the day was over.

Well, he followed instructions, and opened it and read: "Until
7/6, noon, in Trafalger Square.". Since it was January, he went
off and did other things, such as roping calves etc., and returned
to London on 7/6. He never found her again.

She meant every word of it, and she was there on 7/6, but never
found him again.

Your mission, should you care to accept it, is to explain this
paradox. Alternate timelines or universes will not be accepted.

Too easy. June 7th != July 6th. However, your language point is
evident.
 
C

Christian Bau

Severian said:
Too easy. June 7th != July 6th. However, your language point is
evident.

Many years ago, a C++ framework that I investigated for its usefulness
changed a constructor from

Point::point (int width, int height);

to

Point::point (int vertical, int horizontal);

I decided not to use that framework...
 
R

Régis Troadec

Dan Pop said:
In <[email protected]> "Régis Troadec"

Hi,


I was hurt by not seeing *anywhere* in 6.3.2.3 that the conversion
doesn't require a cast. I am still hurt... ;-)

Perhaps one day I'll be right and exhaustive...
Let's now add C99 §6.5.4 concerning the cast operator and the further
reference to simple assignments in §6.5.16.1.
I'm too lazy to find out the interesting and relevant parts in the
paragraphs but I think the reader will find something that prove the
conversion doesn't require a cast.
Am I complete now, or is something missing ?

Regards,

Regis
 
D

Dave Thompson

"Chris Fogelklou" <[email protected]> wrote:

Bitwise operations can only be performed on integral types. If you write an
expression like (p & 1) then p is silently converted to an integral type
by the compiler.

No, at least not silently in conforming mode; for each bitwise
operator (and ~, which for convenience is called arithmetic rather
than bitwise) it is a constraint that the operands be integer types,
and violation of a constraint requires a diagnostic. What happens
after the diagnostic is undefined, and IMO it wouldn't be unreasonable
to convert to integer.

You might be thinking of the logical && and ||, which require only
that the operands can be compared to zero, which works for floating
and pointer as well as integer.

- 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,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top