函数内部的函数声明 - 为什么?

时间:2015-04-20 11:35:47

标签: c function

我正在阅读这本书"用C&#34编程;并在第10章中找到了这样一个例子:

#include <stdio.h>

void test (int  *int_pointer)
{
     *int_pointer = 100;
}

int main (void)
{
     void test (int  *int_pointer);
     int  i = 50, *p = &i;

     printf ("Before the call to test i = %i\n", i);

     test (p);
     printf ("After the call to test i = %i\n", i);

     return 0;
}

我理解这个例子,但我不理解void test (int *int_pointer);内的main行。为什么我要再次定义test的签名?是那个惯用的C?

5 个答案:

答案 0 :(得分:11)

void test (int *int_pointer);只是函数test的声明(或原型)。 main中不需要此声明,因为您已经在main之前有了函数定义。

如果test的定义在main之后,则值得将其声明放在那里让编译器知道{{1}的返回类型,参数数量和参数类型在调用它之前。

答案 1 :(得分:10)

这绝对不是惯用的C,尽管完全有效(多个声明都可以,多个定义都没有)。这是不必要的,所以如果没有它,代码仍然可以正常工作。

如果有的话,也许作者打算做

void test (int *int_pointer);

int main (void) {

    ...

}

如果函数定义放在main ()之后。

答案 2 :(得分:9)

这不是C语言,但仍然有效。

该行是函数test的声明,而不是定义。函数不能多次定义,但有多个声明是有效的。

答案 3 :(得分:5)

它完全是惯用的C,它实际上具有(有限的)实际用途 - 尽管不是这个例子所证明的。

当您在通常的全局级别声明函数或其他名称时,它将被引入声明后面的代码中的所有函数体。一旦引入声明,就无法从作用域中删除声明。该功能对翻译单元的其余部分始终可见。

在支撑块中声明函数或其他名称​​时,声明的范围仅限于该块。声明另一个函数范围内的函数将限制其可见性,并且不会污染全局命名空间或使其对同一翻译单元中定义的任何其他函数可见。

在示例的情况下,这是毫无意义的,因为test的定义也将其纳入所有后续主体的范围 - 但是如果test在另一个翻译单元中定义,或者即使它仅在此TU的最底部定义,将声明隐藏在main内将保护之后定义的任何其他函数,使其无法在其范围内查看其名称。

实际上,这个用途有限 - 通常如果你不想要一个功能可见,你把它放在另一个翻译单元(最好是它static) - 但你可能设想一种情况,你可能想要使用这种能力来构建一个模块加载系统,该系统不会导出其组件的原始声明,或类似的东西(事实上,这并不依赖于{ {1}} /单独的目标文件可能与嵌入式/非托管目标环境有一些相关性,其中链接步骤可能不像在PC上那样工作,从而允许您实现纯粹的命名空间保护措施 - {{1基于构建系统)。

示例:

static

答案 4 :(得分:4)

这不是惯用的;您通常会在代码中看到它,但是在按顺序获取头文件时会遇到问题。

任何功能只能在一个文件中使用,或者在多个文件中使用。如果它仅在其自己的文件中使用,则它应该是静态的。如果它在多个文件中使用,则其声明应该在头文件中,并且使用它的任何人都应该包含头文件。

你在这里看到的是非常糟糕的样式(函数应该是静态的,或者声明应该从头样式中获取),并且也毫无意义,因为编译器已经可以看到声明了。由于该函数在同一个文件中,因此并不危险;如果声明和函数不匹配,编译器会告诉你。当函数在不同的文件中时,我经常看到这种事情; 是危险的。如果有人更改了该功能,该程序可能会崩溃或行为异常。