【问题标题】:Any good use for nested function in C?C中的嵌套函数有什么好处吗?
【发布时间】:2011-05-16 16:31:47
【问题描述】:

我在某处读到 C 中允许嵌套函数(至少 GNU 编译器允许这样做)。考虑以下代码:

/* nestedfunc.c */
#include <stdlib.h> /* for atoi(3) */
#include <stdio.h>

int F (int q)
{
  int G (int r)
  {
    return (q + r);
  }
  return (G (5));
}

int main (int argc, const char* argv[])
{
  int q = 0;
  if (argc > 1)
  {
    q = atoi (argv[1]);
  }

  printf ("%d\n", F (q));
  return 0;
}

编译运行:

gcc -o nestedfunc -O2 -s -Wall nestedfunc.c
me@mybox:~/college/c++/other stuff$ ./nestedfunc 8
13
me@mybox:~/college/c++/other stuff$

我还了解到其他一些编程语言支持这些。我的问题是:嵌套函数有什么有用的用途?提前致谢。

【问题讨论】:

  • 重要的是要意识到这些甚至不是远程标准,而是特定于编译器的扩展,所以如果您关心可移植性,请远离它。

标签: c nested-function


【解决方案1】:

嵌套函数可以访问外部函数的局部变量。有点像闭包,您可以获取一个指向嵌套函数的指针并将这个指针传递给其他函数,并且嵌套函数将可以访问当前调用的局部变量(如果此调用已经返回,则会发生坏事)。因为 C 运行时系统不是为此而设计的,所以函数指针通常只是指向函数第一条指令的指针,而指向嵌套函数的指针只能通过在堆栈上编写一些代码并将指针传递给它来完成。从安全角度来看,这是一个坏主意。

如果您想使用嵌套函数,请使用具有适当支持它们的运行时系统的语言。要在 C 中实现类似的结果,请将“外部函数的局部变量”放入上下文结构中并手动传递。

【讨论】:

  • +1 用于解释 gcc 嵌套函数的唯一真正用途。
【解决方案2】:

在其他编程语言(例如 Python、Ruby)中,函数是第一类对象。你有closures 这是强大的抽象概念。在python中你可以这样做:

def curry(func):
    from inspect import getfullargspec
    args = getfullargspec(func)
    num_args = len(args[0])

    def new_func(list_args, *args):
        l = len(list_args) + len(args)
        nl = list_args + list(args)
        if l > num_args:
             raise TypeError("Too many arguments to function")
        elif l == num_args:
             return func(*nl)
        else:
             return lambda *new_args: new_func(nl, *new_args)

    return lambda *args: new_func([], *args)

这是 curry 装饰器,它接受一个函数并使其咖喱。

【讨论】:

  • 注意标题中的“in C”。 C中的高阶函数......当我想到它的样子时,我的眼睛流血了:(
  • “我还读到其他一些编程语言支持这些。我的问题是:嵌套函数有什么有用的目的?提前谢谢。”我回答了这个。 :)
  • 是的。我只是喜欢对 C 发表刻薄的评论 :) (无关:我想知道 OP 是否会承认这是有用的。根据我的经验,许多人在实际使用之前并不认为所有这些花哨的 FP 东西有用)
【解决方案3】:

一般来说,嵌套函数通常是一个辅助函数,它只在另一个函数内部使用。它有点像static 函数(具有文件范围),但更加本地化(仅函数范围)。

嵌套函数不是标准的 C,因此没有理由在该语言中使用它们。

【讨论】:

    【解决方案4】:

    嵌套函数提供encapsulationlexical scope

    在您的示例中,G() 只能由F()F() 中定义的其他函数调用。

    【讨论】:

    • 特别是在 C 和其他没有命名空间的语言中(例如,理论上 PHP 直到 5.x,实践中的大多数 PHP),避免命名空间污染可能非常有用。
    • @delnan:我看不出这有什么用。 C 具有 static 范围,如果这还不足以避免名称冲突,您可以简单地将 your_favorite_uuid_your_main_function_name_ 添加到其辅助函数的名称之前。
    • @R..your_favorite_uuid_your_main_function_name_ 是命名空间的杀手级原因。另外,我说“命名空间 污染 ” - 你可以避免名称冲突,但无论如何你都会污染全局命名空间,除非你使用 static 或嵌套函数来限制范围。
    • 我会犹豫是否称它为 pollution,只要选择的名称没有与其他库或应用程序选择的名称发生冲突的实际机会。当然它很丑,但它不会破坏任何东西。即使使用命名空间,您也必须确保命名空间的名称不会冲突。
    猜你喜欢
    • 2015-08-01
    • 2012-08-08
    • 2023-04-06
    • 2022-01-22
    • 2023-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多