Reputation: 31389
Take this code for instance:
const char *s;
char *t = s;
This would emit this: warning: assignment discards 'const' qualifier from pointer target type
It's easy to silence the compiler, by just adding a cast:
char *t = (char*)s;
And you can do similar things for regular variables and not just pointers, and it does not only apply to the const qualifier. You can basically cast from any type to any type, even if some of those casts would cause trouble.
I have also read that you never should cast malloc
because a cast to and from void pointer is always safe.
But what does the casting actually do? Does it do something else than just preventing the compiler from spitting out warnings. When are explicit casts actually necessary?
Clarification:
I'm talking about assignments here. Not things like double res = (double)a / b
. In that situation, I know what the cast does, and in this case we could easily get rid of the explicit cast in favor of an implicit cast like this: double c = a; double res = c/b;
or just double res = (1.0 * a) / b
Upvotes: 2
Views: 954
Reputation: 222933
C 2018 6.5.16.1 1 specifies constraints for the simple assignment operator. For left and right operands that are both pointers other than pointers to void
, these say:
One of the following shall hold: … both operands are pointers to qualified or unqualified versions of compatible types, and the type pointed to by the left has all the qualifiers of the type pointed to by the right; …
Thus, the C standard requires that pointers be of the same “kind” (compatible types) and that the assignment not remove any qualifiers (the left side has all the qualifiers of the right side, but possibly more). If this requirement is violated, the compiler must issue a diagnostic message (although it can still choose to accept the program; the message can be a warning rather than an error).
6.5.4 specifies constraints for casts, in paragraphs 2 to 4. None of them limit conversions from one pointer type to another. Therefore, you can specify any pointer conversion with a cast, and the compiler is not required to issue a diagnostic (although some may choose to).
The underlying philosophy is that an assignment allows you to implicitly do conversions that are “normal” uses of pointers, but explicitly using a cast allows “special” uses of pointers.
The fact that a particular conversion is allowed with a cast does not necessarily mean it is meaningful or well-defined. 6.3.2.3 defines some rules for conversions of pointers. For example, an int *
may be converted to a char *
, and the resulting pointer can be used to examine the bytes that represent an int
. But converting a char *
to an int *
may result in undefined behavior. So a cast will allow you to do a conversion, but whether the result is useful or is what you want depends on other rules in the C standard.
When a conversion is allowed and defined, it will have the same effect whether it occurs implicitly by assignment or explicitly by cast. The cast does not change what the conversion is; it only changes whether it is allowed (without a diagnostic) or not.
Upvotes: 2