【问题标题】:sqrt() - Why am I allowed to provide an argument of int and not only double and the output is also right?sqrt() - 为什么我可以提供 int 的参数,而不仅仅是 double 并且输出也是正确的?
【发布时间】:2025-12-03 02:40:01
【问题描述】:

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

在 C99 中,原型的声明是:

双平方(双倍);

#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)); 

}

输出:

 Number      Square Root of Number

 9           3.000000 

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

这是跨入未定义行为吗?

我正在使用 gcc。


这个问题已经被问过两次 C++,但不是 C,所以我的问题是关于 C 的。 无论如何,我提供了 C++ 问题的链接:

Why does sqrt() work fine on an int variable if it is not defined for an int?

Why is sqrt() working with int argument?

【问题讨论】:

    标签: c int arguments language-lawyer sqrt


    【解决方案1】:

    这不是未定义的行为。

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

    int i = 4;
    double d = i;
    

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

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

    相反,如果您在格式字符串需要double 时将int 传递给printf,即:

    printf("%f\n", 4);
    

    然后你有未定义的行为。这是因为参数的类型在编译时是未知的,所以不会发生隐式转换。

    【讨论】:

    • 非常感谢。还有我想要的标准引用。非常感谢你的努力。我还有一个问题:这是否也适用于char?就像 f.e.当我举你的例子时:char c = 4; double d = c; 或在我给定的例子中:printf("\t %d \t\t\t %f \n",i, sqrt(c)); 或者这仅适用于从 intdouble 的转换?
    • @RobertS-ReinstateMonica A char 也可以隐式转换为 double。此外,在可以使用int 的地方,char 可以升级int。这包括作为printf 的参数,因此您可以使用%d 格式说明符传递char 值。
    最近更新 更多