我是C语言的初学者,在JavaScript之后开始,不能习惯这些类型。
好的math.h的sqrt函数应该与双精度函数一起使用,据我所知,在C中你不能将错误的类型作为参数传递。
但是当我走的时候:
int b = sqrt(1234); //it works
也是如此
float b = sqrt(1234); // it works
int b = sqrt(1234.22) // it works
为什么所有这些都有效?这个过程看起来像什么?
我的猜测是:无论我通过什么,sqrt的参数都会自动转换为double 如果我指定的变量是int类型,则结果double将转换为int。
然后有两个问题?
1)如果我传递了错误的类型但没有使用sqrt,为什么我会遇到其他函数的错误? 2)如果我们可以像这样将int转换为float
float b = 123.44
int a = b;
为什么我们需要这个?
float b = 123.44
int a = (int) b;
答案 0 :(得分:1)
为什么所有这些[两次初始化]都有效?
第一个初始化float b = sqrt(1234)
有效,因为语言在调用1234
之前将整数文字double
“向上转换”为sqrt
,然后将结果转换为float
}。
第二个初始化int b = sqrt(1234.22)
的工作原理相同,除了这次编译器在调用之前没有up 1234.22
文字,因为它已经是double
类型。< / p>
这在C99标准中讨论过:
6.3.1.4.1:当实数浮动类型的有限值转换为
_Bool
以外的整数类型时,小数部分将被丢弃。6.7.8.11:标量的初始值设定项应为单个表达式,可选择用大括号括起来。对象的初始值是表达式(转换后)(强调添加)。
-
为什么我们需要这个[cast
int a = (int) b;
]?
为了便于阅读,您可以插入演员表,但标准不需要它(demo)。
答案 1 :(得分:0)
为了使编译器能够将正确的参数传递给函数,需要告诉它函数期望的类型。这意味着您必须提供函数的完整声明,并且可以通过两种方式完成。
如果是sqrt()
,您通常会#include <math.h>
。另一种方法是在源代码中明确声明该函数:double sqrt (double);
。
一旦编译器知道函数期望和返回的类型,如果可能的话,它将把参数转换为正确的类型。 int
和double
可以隐式转换。
如果您未能声明函数的参数类型,默认参数提升将应用于参数,这意味着小整数类型将转换为int
,并float
将转换为double
。您的int
参数将使用某种特定于实现的方法盲目地传递为int
,而sqrt()
函数将使用其他特定于实现的方式将其参数检索为double
方法。如果两种方法不同,这显然不会正常工作,这就是为什么在没有完整声明的情况下将错误的类型传递给函数会导致未定义的行为。
在C标准的最后两个版本中,不允许在没有事先声明的情况下调用函数,并且编译器需要发出诊断消息。但是,由于历史原因,此声明不需要提供参数类型。