Many conversions are implicit in C:
- between all numeric types,
- between data pointer types and the
void *
type,
- from an array type to its corresponding pointer type (this is called decaying)
- from a non const type to its const equivalent,
Compilers usually do not issue diagnostics about these because the behavior is defined by the standard, but some of these conversions indicate a programming error, such as double x = 1 / 2;
. To help programmers avoid these silly mistakes, the compiler can be instructed to issue warnings or even errors.
It is wise to use these extra warnings. gcc
will do that if invoked with -Wall -Wextra -Wconversion -Wfloat-conversion
and clang
has similar settings: clang -Wall -Weverything
. Your first assumption was not unrealistic, but gcc
is notoriously lenient with sloppy code by default and you were instructed to not use any flags. Even worse: to stay compatible with old Makefiles, gcc
defaults to c89 and will complain about the use of some c99 features.
Note that the language defines the behavior when it can determine that they are necessary, but sometimes it cannot:
float f = 10.7;
printf("%d\n", f);
In this case, the standard specifies that f
should be passed to the variadic function printf
as a double
, but printf
expects an int
argument for the specifier %d
. Your second assumption would be correct here, an explicit conversion with an (int)
cast is required. Again, good compilers can issue a diagnostic for these errors if instructed to do so.
Furthermore, some implicit conversions can be determined at compile time to lose information of even invoke undefined behavior, such as:
char x = 300;
int x = 1e99;
It would help if the compiler issued diagnostics for these even without a strict option.
Lastly, some conversions will loose information but are more difficult to detect in the general case:
double f = 10000000000000;
char a = f;
float f = d;
int i = d;
The language does define the behavior only if the receiving type is large enough for the integral part, otherwise the behavior is undefined even with an explicit cast. Whether the programmer wants a warning or not in these cases is a matter of personal choice.
Regarding why the conversion from a floating point type to an integer type is defined to round toward 0
, it might be simpler to do so, and you can get other behaviors by using round()
or adding 0.5
before the conversion if you know the value is positive.
float
expression to anint
variable is completely specified by the C standard. How should the compiler know that the programmer does not intend exactly that to happen? – Maltoseint
. – Showiness