C 语言中的嵌套函数

Nested function in C

提问人:Sachin 提问时间:4/9/2010 最后编辑:Antti Haapala -- Слава УкраїніSachin 更新时间:7/22/2020 访问量:114014

问:

我们可以在 C 语言中有一个嵌套函数吗?嵌套函数有什么用?如果它们存在于 C 语言中,它们的实现是否因编译器而异?

嵌套的 c 函数

答:

43赞 Marcelo Cantos 4/9/2010 #1

不,它们在 C 中不存在。

它们在 Pascal 等语言中使用(至少)有两个原因:

  1. 它们允许在不污染命名空间的情况下进行功能分解。您可以定义一个公开可见的函数,该函数通过依赖一个或多个嵌套函数将问题分解为更小的逻辑部分来实现某些复杂的逻辑。
  2. 在某些情况下,它们简化了参数传递。嵌套函数可以访问外部函数范围内的所有参数以及部分或全部变量,因此外部函数不必将一堆局部状态显式传递到嵌套函数中。
142赞 James McNellis 4/9/2010 #2

不能在标准 C 中的另一个函数中定义一个函数。

您可以在函数内部声明函数,但它不是嵌套函数。

GCC 具有允许嵌套函数的语言扩展。它们是非标准的,因此完全依赖于编译器。

22赞 CB Bailey 4/9/2010 #3

不,你不能在 中嵌套函数。最接近的方法是在另一个函数的定义中声明一个函数。但是,该函数的定义必须出现在任何其他函数体之外。C

例如

void f(void)
{
    // Declare a function called g
    void g(void);

    // Call g
    g();
}

// Definition of g
void g(void)
{
}

评论

9赞 Sachin 4/9/2010
如果函数 g 以这种方式声明,那么它的范围是什么?
6赞 CB Bailey 4/9/2010
声明的作用域与任何其他声明一样,因此在本例中,直到函数结束。当然,一旦 的定义在文件后面可见,该声明就包含在翻译单元其余部分的范围内。此外,您可以在 C 中调用函数,而无需在作用域中显示声明,即使这是不可取的。g
28赞 zoli2k 4/9/2010 #4

嵌套函数不是 ANSI C 的一部分,但是,它们是 Gnu C 的一部分。

评论

0赞 Sachin 4/9/2010
如果它们是 Gnu C 的一部分,有什么意义
5赞 zoli2k 4/9/2010
@Sachin 有助于理解为什么带有嵌套函数的 C 代码可以用 gcc 编译。这些信息具有教育价值。此外,这个问题没有具体说明它是否仅限于 C89、C99 或 GNU C
5赞 nategoose 4/9/2010
GCC 支持的其他语言确实有它们(据我所知的 ADA 和 Pascal),因此很可能它很容易添加到 C 实现中,或者它被添加到 C 中是为了准备支持需要它们的语言。
0赞 mikeTronix 12/20/2016
MATLAB 还具有嵌套函数。
4赞 PauliL 4/9/2010 #5

正如其他人所回答的那样,标准 C 不支持嵌套函数。

在某些语言中,嵌套函数用于将多个函数和变量包含在一个容器中(外部函数),以便从外部看不到单个函数(不包括外部函数)和变量。

C 语言中,这可以通过将此类函数放在单独的源文件中来完成。 将 main 函数定义为全局函数,将所有其他函数和变量定义为静态函数和变量。 现在,在此模块之外仅可见 main 函数。

评论

0赞 Adrian Panasiuk 11/5/2013
如果有递归 ->->->,那么将有两个不同的帧保持,所以你不能只放一个静态全局。outernestedouternestedint declared_in_outerdeclared_in_outer
9赞 Jon Green 5/2/2014 #6

我之所以提到这一点,是因为现在很多人都在使用 C++ 编译器(例如 Visual C++ 和 Keil uVision)来做到这一点,所以你可以利用这个......

虽然在 C 中还不允许,但如果您使用的是 C++,则可以使用 C++11 中引入的 lambda 函数实现相同的效果:

void f()
{
    auto g = [] () { /* Some functionality */ }

    g();
}

评论

6赞 Virgile 6/25/2014
这个问题是关于C的,而不是C++的
16赞 www-0av-Com 4/8/2015
@Virgile - 问题还特别指出“是否允许在任何其他语言中使用嵌套函数?乔恩的回答帮助了我。
-1赞 midnightCoder 4/1/2015 #7

这不是 C 语言中的嵌套函数吗?( 函数 displayAccounts() )

我知道我本可以以不同的方式定义函数并传递变量和不传递的变量,但无论如何效果很好,因为我需要多次打印帐户。

(取自学校作业的狙击手)...

//function 'main' that executes the program.
int main(void)
{
    int customerArray[3][3] = {{1, 1000, 600}, {2, 5000, 2500}, {3, 10000, 2000}};  //multidimensional customer data array.
    int x, y;      //counters for the multidimensional customer array.
    char inquiry;  //variable used to store input from user ('y' or 'n' response on whether or not a recession is present).

    //function 'displayAccounts' displays the current status of accounts when called.
    void displayAccounts(void)
    {
        puts("\t\tBank Of Despair\n\nCustomer List:\n--------------");
        puts("Account #    Credit Limit\t  Balance\n---------    ------------\t  -------");
        for(x = 0; x <= 2; x++)
        {
            for(y = 0; y <= 2; y++)
                printf("%9d\t", customerArray[x][y]);
            puts("\n");
        }
    }

    displayAccounts();  //prints accounts to console.
    printf("Is there currently a recession (y or n)? ");


//...

    return 0;
}

评论

4赞 Nate Eldredge 4/13/2015
这不是法律标准 C。如果它适用于您的编译器,那是因为您的编译器提供了对标准 C 语言的扩展;从某种意义上说,你的编译器正在编译一种不同的语言,严格来说,它不是 C。
1赞 midnightCoder 11/16/2016
感谢您的输入。从那以后,我学会了声明、定义和使用函数的正确方法。回顾>有点尴尬.<
2赞 chqrlie 6/5/2019
@midnightCoder:您可以随时删除您的答案:)
0赞 Christoffer Bubach 5/14/2021
有很多较旧的源代码使用它,例如这个链接。它可能是 K&R C 的一部分,还是当时更常见的编译器支持?history.dcs.ed.ac.uk/archive/languages/imp-pdp15/hdcomp.c.html
3赞 kyriakosSt 4/25/2017 #8

为了回答第二个问题,有一些语言允许定义嵌套函数(可以在此处找到列表:nested-functions-language-list-wikipedia)。

在 JavaScript 中,这是最著名的语言之一,嵌套函数(称为闭包)可能是:

  • 在对象的构造函数中创建类方法。
  • 实现私有类成员以及 setter 和 getter 的功能。
  • 不要污染全局命名空间(当然,每种语言都适用)。

仅举几例......

-2赞 AnArrayOfFunctions 8/9/2019 #9

或者你可以聪明一点,利用预处理器来发挥你的优势():source.c

#ifndef FIRSTPASS
#include <stdio.h>

//here comes your "nested" definitions
#define FIRSTPASS
#include "source.c"
#undef FIRSTPASS

main(){
#else
    int global = 2;
    int func() {printf("%d\n", global);}
#endif
#ifndef FIRSTPASS
    func();}
#endif

评论

1赞 iono 7/13/2022
你认为使用已经很糟糕的预处理语言来破解糟糕的 C 语言是“聪明的”,这一事实反映了你的判断力很差
0赞 AnArrayOfFunctions 7/13/2022
@iono,你对一个 3 年前的帖子发表评论只是为了批评一个有效的解决方案,这一事实对你的判断反映得很差。顺便说一句,我不认为 C 语言是否“可怕”是你的决定——它仍然被广泛使用。