4

在 C/C++ 中显式原型本地函数有什么好处,而不是在使用前定义函数?本地我的意思是函数仅在其源文件中使用。一个例子是这样的:

#include "header.h"

static float times2(float x){
    return 2*x;
}

static float times6(float x){
    return times2(3*x);
}

int main(void){

    // Other stuff ...

    float y = times6(1);

    // Other stuff ...
}

与此相反:

#include "header.h"

// Local function prototypes
static float times2(float);
static float times6(float);

// Main
int main(void){

    // Other stuff ...

    float y = times6(1);

    // Other stuff ...
}

// Local functions definition
static float times2(float x){
    return 2*x;
}

static float times6(float x){
    return times2(3*x);
}

就我个人而言,我更喜欢使用第一个选项,因为要编写的代码更少,并且(对我而言)文件更易于阅读,但现在我想知道是否有任何技术原因更喜欢第二个选项。

编辑:我在 times2() 和 times6() 中添加了静态,请参阅下面的@Gangadhar 答案和评论。

4

5 回答 5

3

除了需要作为前向引用之外,声明 local( statc) 函数的优势在于组织性。同样的道理也适用于静态变量。

如果一个文件有几十个函数(和变量),前面的本地定义有助于组织。人们可能希望将这么大的集合保持在一个订单 (AZ) 中。此命令可能/可能不适用于前向引用。通过列出所有函数/变量((*.h` 文件中的全局变量)和此处 (*.c) 中的局部变量,可以维护组织,即使在代码的生命周期内前向引用需求可能会发生变化

// function/variable prototypes
static float pi;
static float pi2;
static float times2(float);
static float times3(float);
static float times4(float);
static float times5(float);
static float times6(float);
static float times7(float);
static float times8(float);
static float times9(float);
于 2013-10-22T10:15:23.063 回答
2

在某些情况下,您需要事先声明函数原型,即编译器需要知道函数原型才能使用该函数。

考虑这些没有什么特别有用的功能:

int foo(int x)
{
    if(x < 1) return x;
    else return x + bar(x-1);
}

int bar(int x)
{
    if(x < 3) return x;
    return x * foo(x-1);
}

如果你尝试编译它,编译器会生你的气:

错误:未在此范围内声明“bar”

您需要将缺少的原型放在使用它的函数前面:

int bar(int);
// as above unchanged

这是编译器要求您在函数之前放置函数原型的唯一情况。在所有其他情况下,将原型放在任何地方都是完全合法的,只要你愿意,这也是合法的:

int foo(int);
int bar(int);
int foo(int);
int bar(int);

虽然显然是多余的(请不要这样做)。有些人认为将文件中每个函数的函数原型放在文件顶部是一种很好的风格,因为

  1. 您不必关心编译器要求您再执行此操作的情况,并且有些人显然无法解释编译器的错误消息(我认为这非常简洁),并且
  2. 您可以在一个视图中看到文件提供了哪些功能以及如何调用它们。

但这正是风格讨论。我喜欢让我的代码尽可能短,所以我只会使用编译器需要的原型,但这纯粹是一个品味和惯例的问题。在罗马时,做罗马人或类似的事情。

于 2013-10-22T19:25:15.163 回答
0

当两个函数相互调用时,即 FuncA() 调用 FuncB(),反之亦然,则必须声明任何一个函数。这是@MM(以上答案)描述的条件。

但在任何正常情况下,声明函数只是一种约定,因开发人员而异。

于 2013-10-22T09:26:44.290 回答
0

如果提到原型:函数 times2,times6 期望浮点参数在调用时位于堆栈或寄存器中。如果省略原型,编译器将无法强制执行此操作,并且上述函数最终将操作堆栈上的其他一些数据。通过包含函数原型,您通知编译器这两个函数都采用一个浮动参数,并且您使编译器能够捕获此类错误。

于 2013-10-22T09:21:01.530 回答
0

必需的前向引用和外部是使用原型的唯一原因。原型是噪音。在使用之前声明函数。它更干净,只需要您更改一次界面。我不明白人们为什么要使用它们。

于 2019-09-28T04:21:24.797 回答