【问题标题】:C function definition and declarationC函数定义和声明
【发布时间】:2015-11-13 20:54:02
【问题描述】:

我是一名 Java 程序员,我学过一点 C++,现在我正在为我的工作学习一点 C。 我无法理解关于函数声明/定义和相关函数调用的 C 行为。 从 K&R 我知道在 C 中(与 C++ 非常不同)我可以调用以前没有声明过的函数,并且编译器会假定类型的隐式声明:

int main() 
{
  function(10);   // implicit function declaration ( int function() )
}

而且我知道这样的声明意味着一个函数接受固定但不定数量的任何类型的参数(只要每个调用与其他调用一致)。我知道这是 C89 之前的 K&R C,但我也想知道它是如何工作的。 现在,我有这个测试代码,我看不懂:

#include <stdio.h>

function();

int main()
{
  printf("hello %d",function(1,2,3));
  implicit(11,12,32);     // implicit function declaration ( implicit() )
}


int implicit(int b)
{

}

function(int a)
{

}

function 的情况下,声明(假定返回类型为 int,不假设参数)确实与定义匹配(编译器发出警告)但如果我用错误的参数调用函数,它编译! 函数implicit 相同。 看不懂。。

【问题讨论】:

  • 这类问题正是 C++ 需要提前声明函数的原因。这是我在 C 中坚持的做法。
  • 这是旧式的、已弃用的、糟糕的代码。作为一个 C 初学者,你真的需要知道糟糕的代码是如何工作的吗?
  • 是的,C 需要 .h 文件来放置函数定义(原型)。它将假定它们在编译时存在于某个地方,然后在运行时失败。看看 stdio.h 文件。
  • @n.m.是的,因为我偶然发现了它,因为例如,不带参数的函数声明是一个不为我接受参数的函数,了解不推荐使用(但编译器支持)的代码有助于我了解要避免的编码风格
  • 如果你正在为你的工作学习 C,你应该学习一些有用的东西,比如如何正确地声明一个具有格式良好的函数原型的函数。而且您应该使用现代编译器,当您出错时会发出警告。最重要的是,修复编译器警告您的所有内容。永远不要忽视警告。

标签: c declaration definition


【解决方案1】:

您必须记住的是,在声明和定义方面,编译几乎是连续的。当编译器处理对function 的调用时,它所拥有的只是声明,正如您所说,对参数没有任何假设,这意味着您可以使用您喜欢的任何参数调用该函数。当编译器看到定义时,它不会返回发出有关调用的错误,但它可能会发出警告。

至于implicit 函数,当编译器第一次看到它时,它会假定参数是您在推断声明时在调用中传递的内容。同样,它在稍后看到声明之前不会知道任何其他内容,然后可能会发出警告。

调用具有多个或很少参数的函数会导致未定义的行为,这就是为什么隐式声明的函数如此危险,以及在声明函数时使用空参数列表。

【讨论】:

  • 所以,虽然在 C++ 中每个函数名都使用原型声明,并且原型必须与定义匹配(在相同或另一个编译单元中),但我可以在 ANSI C 中使用相同的语法,但是如果我使用旧式(我不会)C,并使用隐式或无参数函数声明,编译器不会强制声明/定义匹配,一切都可能发生?
  • @Luca 对一个长问题的简短回答是肯定的。
【解决方案2】:

真的没有什么好理解的。这是一种遗留的 C 行为,是一种极其宽松的语言。只要编译器能生成汇编指令,它就会很乐意编译你的代码,然后交给你来收拾烂摊子。

这就是它在您的情况下编译的原因。编译器可以生成指令来调用函数 - 所以它会按照要求进行。

【讨论】:

  • 是的,但从 C++ 的角度来看,这很难理解。让我感到困惑的是编译器的行为,它允许一个函数调用“匹配”先前的声明(隐式或允许任何参数)但随后的定义不同。
猜你喜欢
  • 1970-01-01
  • 2021-05-30
  • 1970-01-01
  • 1970-01-01
  • 2018-11-09
  • 1970-01-01
  • 2020-10-07
  • 2023-03-12
相关资源
最近更新 更多