sqrt() - 为什么我可以提供 int 参数而不是 double 并且输出也是正确的?

Rob*_*rtS 3 c int arguments sqrt language-lawyer

我想知道为什么编译器让这个通过并给出正确的输出,尽管sqrt()从它的原型通常应该只得到一个double值作为参数:

在 C99 中,原型的声明是:

双sqrt(双x);

#include <stdio.h>
#include <math.h>

int main (void)
{  
   int i = 9;

   printf("\t Number \t\t Square Root of Number\n\n");

   printf("\t %d \t\t\t %f \n",i, sqrt(i)); 

}
Run Code Online (Sandbox Code Playgroud)

输出:

#include <stdio.h>
#include <math.h>

int main (void)
{  
   int i = 9;

   printf("\t Number \t\t Square Root of Number\n\n");

   printf("\t %d \t\t\t %f \n",i, sqrt(i)); 

}
Run Code Online (Sandbox Code Playgroud)

如果我给sqrt()函数一个intas 参数,为什么编译器至少不抛出警告并且给定的输出是正确的?

这是进入未定义行为吗?

我正在使用 gcc。


这个问题已经针对 C++ 提出了两次,但没有针对 C,所以我的问题是针对 C 的。无论如何,我提供了 C++ 问题的链接:

如果没有为 int 定义,为什么 sqrt() 可以在 int 变量上正常工作?

为什么 sqrt() 使用 int 参数?

dbu*_*ush 7

这不是未定义的行为。

该函数被定义为接受类型为 的参数double。因为参数的类型是已知的,所以可以传递 an ,int因为它可能会隐式转换为 a double。这就像你做的一样:

int i = 4;
double d = i;
Run Code Online (Sandbox Code Playgroud)

关于函数调用运算符的C 标准第 6.5.2.2p7 节详细说明了函数参数的转换规则()

如果表示被调用函数的表达式的类型确实包含原型,则参数将像通过赋值一样隐式转换为相应参数的类型,将每个参数的类型视为其声明的非限定版本类型。函数原型声明符中的省略号表示在最后一个声明的参数之后停止参数类型转换。默认参数提升是在尾随参数上执行的

相反,如果你通过了intprintf时格式字符串需要一个double,即:

printf("%f\n", 4);
Run Code Online (Sandbox Code Playgroud)

然后你有未定义的行为。这是因为参数的类型在编译时是未知的,因此无法进行隐式转换。