简体   繁体   English

C:数据类型。 sqrt函数与int一起工作的原因是什么?

[英]C: datatypes. sqrt function working with int why?

I am beginner in C, started after JavaScript and cannot get used to these types. 我是C语言的初学者,在JavaScript之后开始学习,无法适应这些类型。

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. 好的math.h的sqrt函数应该可以使用double值,据我所知,在C语言中,您不能将错误的类型作为参数传递。

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. 我的猜测是:无论我通过什么,sqrt的参数都会自动转换为double,如果我要分配给的变量为int类型,则将double转换为int。

Then two questions? 然后两个问题?

1) why do I get an error with other functions if I pass the wrong type but not with sqrt? 1)如果我传递了错误的类型而不是sqrt,为什么其他函数会出错? 2) if we can just convert int to float like this 2)如果我们可以像这样将int转换为float

 float b = 123.44
 int a = b;

why do we need this? 我们为什么需要这个?

 float b = 123.44
 int a = (int) b;

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 . 第一个初始化float b = sqrt(1234)之所以起作用,是因为该语言在调用sqrt之前将“整数”字面量1234 “转换”为double ,然后将结果转换为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 . 第二个初始化int b = sqrt(1234.22)出于相同的原因工作,除了这次编译器不必在调用之前上载1234.22常量,因为它已经是double类型了。

This is discussed in C99 standard: 在C99标准中对此进行了讨论:

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.3.1.4.1:当实数浮点型的有限值转换为_Bool以外的整数类型时,小数部分将被丢弃。

6.7.8.11: The initializer for a scalar shall be a single expression, optionally enclosed in braces. 6.7.8.11:标量的初始化程序应为单个表达式,可以选择用花括号括起来。 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; 我们为什么需要这个[cast int a = (int) b; ]? ]?

You may insert a cast for readability, but the standard does not require it ( demo ). 您可以插入强制类型转换以提高可读性,但是标准不需要强制转换( demo )。

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> . 对于sqrt() ,通常应#include <math.h> The other way is to declare the function explicitly in your source code: double sqrt (double); 另一种方法是在源代码中显式声明该函数: 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. intdouble可以隐式转换。

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 . 如果您未能声明该函数的参数类型,则默认的参数提升将应用于参数,这意味着较小的整数类型将转换为int ,而float将转换为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. 使用某些特定于实现的方法,您的int参数将作为int盲目传递,而sqrt()函数将使用其他特定于实现的方法将其参数检索为double 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. 在C标准的最后两个版本中,不允许在没有事先声明的情况下调用函数,并且要求编译器发出诊断消息。 However, for historical reasons, this declaration is not required to provide the types of the parameters. 但是,由于历史原因,不需要此声明来提供参数的类型。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM