There are implicit and explicit conversions. A cast is always an explicit conversion and uses the (type)
cast operator.
C has quite decent type safety when it comes to pointers. Apart from the special case of null pointer conversions, the only implicit pointer conversion allowed is between an object pointer and a pointer to void
. Given that no type qualifiers are dropped. void*
is not a generic type for function pointers though - no such type exists. As per C17 6.3.2.3/8, it's fine to convert between different function pointer types though, as long as the pointer is de-referenced with the correct type.
The specific rules for what's allowed and what isn't is found in C17 6.5.16.1 - Simple assignment. An assignment that fulfil the rules there would implicitly invoke the applicable conversion rule and it's a so-called "lvalue conversion" basically meaning that you can add type qualifiers to the left operand but you can't discard qualifiers present for the right operand.
Generally, 6.3.2.3 says what kind of conversions that can be done in general and 6.5.16.1 says what conversions that are allowed to be carried out implicitly during assignment.
To allow implicit conversions between various integer and floating point types is arguably a design flaw in the C language - it's a constant source of subtle and often severe bugs. Why C++ decided to fix it by enforcing explicit conversions everywhere. So the real question here is perhaps rather: why does C allow implicit conversions of some types?
{ auto int x;
orextern void func (void);
– Confidentlong long ll = LLONG_MAX; int i = ll;
both clang 13.0.0 and gcc 11.2.0 under-std=c11 -pedantic
produce no warnings. – Blueweedint i = ll;
MS VC gives this warning: 'initializing': conversion from '__int64' to 'int', possible loss of data. Crank up your warning levels! – Lexihexadecimal floating-point constant
vs.hexadecimal floating constant
. – Blueweed