为什么函数不被认为是C语言中的一等公民

时间:2018-01-04 09:25:04

标签: c

在C(以及许多其他“低级”语言)中,函数具有类型。您可以使用与函数匹配的类型声明变量,并可以为此类变量分配函数,但人们坚持认为函数不是C中的一等公民。

使用指向函数的指针并将函数作为参数传递给其他函数是C中几个标准函数的关键;例如, function setPrint(callback) { var obj = setInterval(function () { var frame = $('#WindowFadeiFrame').get(0).contentDocument; var btn = $('#btn', frame); if (btn.length == 0) { console.log('not found'); } else { btn.click(); console.log('found now'); clearInterval(obj); callback(); } }, 100); } setPrint(callback) function callback() { // write all your code here which need to be executed after finding the control from iframe alert(''); } 要求要传递比较函数,否则它无法执行任何操作。

通过使用函数类型声明带有多个变量的qsort,在C中看到“面向对象”编程并不罕见。回调可以并且通常是(如果不总是 - 我无法想象其他任何方式)使用带有函数类型的变量实现,或struct使用带有函数类型的成员实现回调。

那么,为什么C中的函数不被视为一等公民?

(我确定这是重复的,但我似乎无法在这里找到任何类似的问题)

2 个答案:

答案 0 :(得分:6)

Scala问题上有really good answer by Andreas Rossberg(近似重复),这恰好解释了为什么C / C ++中的函数不是一等函数。引用:

  

“一流”不是一个正式定义的概念,但它通常意味着一个实体有三个属性:

     
      
  1. 它可以无限制地用于“普通”值,即从函数传递和返回,放入容器等的任何地方。

  2.   
  3. 它可以在没有限制的情况下构建,只要“普通”值可以,即在本地,在表达式等中。

  4.   
  5. 它可以用类似于“普通”值的方式输入,即,有一个类型分配给这样的实体,它可以与其他类型自由组合。

  6.         

    对于函数,(2)特别暗示局部函数可以使用范围内的所有名称,即你有词法闭包。它通常还带有一个用于构造的匿名表单(例如匿名函数),但这并不是严格要求的(例如,如果语言具有足够通用的let表达式)。在无类型语言中,Point(3)非常简单。

         

    ...

         
        
    • C / C ++中的函数不是一流的。 虽然(1)和(3)可以通过函数指针获得,但(2)不适用于正常的函数。 (这一点经常被忽视。)
    •   

强调我的

答案 1 :(得分:4)

在hnefatl的理论解释中添加一个例子。在 C 中,int 值是一流的。我们可以添加两个 int 值,创建一个新的 int 值:

 int add(int a, int b)
 {
   return a + b;
 }

类似在 Haskell 中,我们可以组合两个函数(适当类型的)来创建一个新函数:

 compose f g = f . g

h = compose f g 是满足 h(x) = f(g(x)) 的函数。

据我所知,这样的操作不能在 C 中完成。当然在C中通过其他方式也可以达到同样的效果。但是我们无法像计算数字那样轻松自然地计算新函数。