Mcs
Mcs

Reputation: 564

C: datatypes. sqrt function working with int why?

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

Answers (2)

Nisse Engström
Nisse Engström

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

Sergey Kalinichenko
Sergey Kalinichenko

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

Related Questions