C原型函数和C函数调用中的默认参数提升

C原型函数和C函数调用中的默认参数提升,c,prototype,function-prototypes,promotions,C,Prototype,Function Prototypes,Promotions,编辑:实际上这是这个问题的重复- 我是C语言的初学者,虽然我了解函数原型和默认参数提升机制的需要。我还读了几本书 关于这个话题的帖子 我仍然对得到的警告和这个简化片段的最终结果感到困惑 #include <stdio.h> void impl(); int main(void) { impl(3.0); return 0; } void impl(val) { printf("%.2f", val); } 我得到了以下警告:format指定了类

编辑:实际上这是这个问题的重复-

我是C语言的初学者,虽然我了解函数原型和默认参数提升机制的需要。我还读了几本书 关于这个话题的帖子

我仍然对得到的警告和这个简化片段的最终结果感到困惑

#include <stdio.h>

void impl();

int main(void)
{   
    impl(3.0);
    return 0;
}

void impl(val)
{
    printf("%.2f", val);
}
我得到了以下警告:format指定了类型'double',但参数的这一行printf%.2f,val的类型为'int'[-Wformat]

我不明白为什么编译器认为val应该被视为int,而不执行默认参数提升。我还了解到,如果不提供参数类型:

ANSIC编译器将假定您已决定放弃函数原型,并且不会检查参数

打印到控制台的结果是0.00,但据我所知,调用者将在堆栈上放置double,而%f也意味着printf中的double,因此它从堆栈中读取double,结果不应受到影响。虽然这个问题解释了一些细节,但我仍然不理解问题到底是什么。另外,我也找不到在哪里声明没有类型的参数应该被编译器视为int类型

我认为我不理解标准中编写的第6.5.2.2部分函数调用:

如果表示被调用函数的表达式具有不包含原型的类型,则对每个参数执行整数提升,并将具有float类型的参数提升为double。这些被称为默认参数

在Windows 10下使用clang 6.0和-std=c89标志编译。

此:

void impl(val)
不指定val参数的形式类型。这使得它默认为int。这与在运行时传递给函数的值的类型无关,如果函数从未被调用,则同样正确


我认为,省略该类型也是非常老派的,在现代C语言中不受支持。

您已经声明了impl,但它没有原型。您可以使用隐式int参数定义它。这在C90中是允许向后兼容的,但在c99中是禁止的。其他问题是这些问题的后果。@JonathanLeffler是的,我知道我定义了一个带有隐式参数的函数,但我找不到隐式参数被视为int类型的来源。你能给我链接吗?这在C89标准第3.7.1节语义部分中有说明。