Reputation: 564
I am beginner in C, started after JavaScript and cannot get used to these types.
Okay math.h's sqrt function should work with doubles and as far as I understand it, in C you cannot pass the wrong types as parameters.
But when I go:
int b = sqrt(1234); //it works
so does
float b = sqrt(1234); // it works
int b = sqrt(1234.22) // it works
Why are all these working? What does the process look like here?
My guess is: The parameters of sqrt are automatically converted to double regardless of what I pass, and the result double is converted to int if the variable I am assigning to is type int.
Then two questions?
1) why do I get an error with other functions if I pass the wrong type but not with sqrt? 2) if we can just convert int to float like this
float b = 123.44
int a = b;
why do we need this?
float b = 123.44
int a = (int) b;
Upvotes: 0
Views: 1667
Reputation: 4752
For the compiler to be able to pass the correct arguments to a function, it needs to be told what types the function expects. This means that you have to provide a full declaration of the function, and it can be done in two ways.
In the case of sqrt()
you would typically #include <math.h>
. The other way is to declare the function explicitly in your source code: double sqrt (double);
.
Once the compiler knows what types the function expected and returns, it will, if possible, convert the arguments to the correct types. int
and double
can be converted implicitly.
If you fail to declare the types of the parameters for the function, the default argument promotions will be applied to the arguments, which means small integer types will be converted to int
, and float
will be converted to double
. Your int
argument will be blindly passed as an int
using some implementation-specific method, while the sqrt()
function will retrieve its parameter as a double
using some other implementation-specific method. This will, obviously, not work properly if the two methods differ, which is why passing the wrong types to a function without a full declaration results in undefined behaviour.
In the last two versions of the C standard, you are not allowed to call a function without a prior declaration, and the compiler is required to emit a diagnostic message. However, for historical reasons, this declaration is not required to provide the types of the parameters.
Upvotes: 0
Reputation: 726559
Why are all these [two initializations] work?
The first initialization float b = sqrt(1234)
works because the language "upcasts" the integer literal 1234
to double
before calling sqrt
, and then converting the result to float
.
The second initialization int b = sqrt(1234.22)
works for the same reason, except this time the compiler does not have to upcast 1234.22
literal before the call, because it is already of type double
.
This is discussed in C99 standard:
6.3.1.4.1: When a finite value of real floating type is converted to an integer type other than
_Bool
, the fractional part is discarded.6.7.8.11: The initializer for a scalar shall be a single expression, optionally enclosed in braces. The initial value of the object is that of the expression (after conversion) (emphasis added).
-
why do we need this [cast
int a = (int) b;
]?
You may insert a cast for readability, but the standard does not require it (demo).
Upvotes: 1