tfelb said:
Hey group!
I have 2 questions. I saw functions with char *dst = (char *)src. In
that case if I remember what I've learned I assign (an) (the) address
of src to dst. Right?
But I can assign an address with the address operator & too? char *dst
= &src.
What's the difference between *dst = (char *)src and *dst = &src and
what's the recommended style?
It's not a minor style difference, it's a profound difference in
meaning. However, there's also some confusion in what you've written
between declarations and statements. Let me clear up that issue before
going any further. You wrote two very different things that look similar:
char *dst = (char*)src;
This is a declaration of a pointer to char named 'dst'. It is
initialized by converting src into a pointer to char. That pointer value
is stored in dst.
You also mentioned:
*dst = (char*)src;
This is an assignment statement. It takes a pointer named dst,
determines what that pointer points at, and then sets the thing that it
points at equal to (char*)src.
So, the declaration sets the value of 'dst'. The assignment statement
sets the value of the thing that dst points at. These are two very
different things.
(char*)src and &src mean two very different things. In this context, src
is probably a pointer object, whose value is a pointer that points at
some other object (if it's a void*, it might point at itself, but this
is easier to explain if we assume that it doesn't). (char*)src converts
that pointer value into a pointer to char, which will point to the first
byte of whatever object src points at. In contrast, &src creates a
pointer value, which points at src itself, not at the object that src
points at. You're earlier declaration implies that src is a pointer
type, let's call it a T*. Then &src has the type T**. That's not a type
that can be used to initialize the value of dst.
2. The same thing with returning a pointer from a function. If i write
a version of strchr i can return a pointer like
return ptr OR
return (char *)ptr.
The key thing you need to understand about casts is that they are almost
never necessary. Most safe conversions occur implicitly, without you
having to make them explicit by using a cast. Using a cast can hide a
type error, so they should be avoided except when they are actually
necessary.
For most operators, when the two operands need to be the same type, the
"usual arithmetic conversions" (6.3.1.8) happen automatically, to make
them have the same type. When you assign a value to an object, if the
value is not of the same type as the object, it is usually implicitly
converted to the type of the object. The same is true in the definition
of an object, if it is explicitly initialized. It also happens to when
arguments are passed to a function, if that function is declared with a
prototype. Getting back to your question, the implicit conversions also
occur when a function returns a value.
You need a cast if there is no implicit conversion allowed from the
source type to the destination type. You also need a cast if the
implicit conversion is allowed, but would produce a different result
than the conversion that you want to perform. However, these are the
only two cases where a cast is needed, and you should always be
suspicious of the possibility that any cast you read, or are thinking of
writing, might be either unnecessary, or possibly even an error.