Now, in both cases, I'm not doing explicit type conversion but case I work correctly..why?(int is storing double value, which shouldn't work implicitly)
Case 1 involves using the simple assignment operator. The operands satisfy this operator's constraints, specifically utilizing the case
the left operand has atomic, qualified, or unqualified arithmetic
type, and the right has arithmetic type
Note well that the types of the two arguments are not required to be the same. It is sufficient for them to both be arithmetic types. With that being the case, the primary aspect of the specified behavior is
the value of the right operand is converted to the type of the assignment expression and replaces the value stored in the object designated by the left operand.
(Emphasis added.) Thus, you get a conversion even without an explicit cast.
Case 2 is different. Note well the prototype for printf
:
int printf(const char * restrict format, ...);
It is a variadic function, and you're passing the double
among the variadic arguments. Now, when you pass an argument to a prototyped function parameter, you get exactly the same kind conversions that you do in simple assignment, but for arguments to functions with no in-scope prototype and for the variable arguments to variadic functions, you get the "default argument promotions". These consist only of promoting integer types smaller than int
to int
or unsigned int
, and promoting float
s to double
.
In the specific case of printf()
, the behavior is undefined when an actual argument does not match the corresponding field directive. This is your case. More generally, UB occurs for any variadic function when it makes an attempt to interpret one of its variable arguments as being of a type incompatible with that argument's (default-promoted) actual type.