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.