在C语言的所有情况下,函数基本上都被视为指向函数的指针,几乎所有函数都在C ++中。
我想知道为什么它是这样设计的?如果它只是一个函数类型,就像在int
或任何其他原语中的变量一样,那不是很好吗?
typedef void(int) func_t
void foo(int);
void bar(int);
func_t fp = foo; // What's wrong with this?
fp = bar; // Acts like any other primitive
据我所知,函数就像指针而不是原语一样,只会让他们模仿它们的地狱般的错误:P
作为旁注,许多语言做将功能视为一种。比如golang
func foo(int) {}
var fn func(int)
fn = foo
编辑被删除,因为它写得很糟糕。
EDIT2内存中函数的表示与它们在一种语言中的呈现方式无关。该语言旨在弥合硬件和逻辑之间的差距,因此,它将硬件内容包装成更容易理解的概念。
例如,作为地址的数字非常容易出错且难以思考,C提出了给它指针语义的解决方案。现在很明显,指针不应该成倍增加,并且与数字不同。指针实际上形成affine space。
我做了相同的论点,事实上,函数指针应该被认为是指针,尽管它在内存中被表示为一个。
答案 0 :(得分:3)
我会用另一个问题回答你的问题:你如何将一个函数表示为一个值?
一个函数基本上是一个代码块,对吧?而这段代码可以是一个可变长度,对吧?那么,我们如何引用可变长度块呢?我们引用一个指向块开头的指针。
我确定其他答案会更详细,但这对于如何有效地掌握它是完美的。
对于看起来函数是值类型的任何语言,我向你保证在内部表示中有一个指针(或者它只是语法糖)。
答案 1 :(得分:1)
如果它只是一个函数类型,就像在一个类似于int或任何其他原语的变量中那样,那不是很完美吗?
单一函数类型是不可能的,因为语言需要区分采用不同类型参数的函数,获取不同数量的参数,以及返回不同类型的值。
您可以为给定的参数集和特定的返回类型定义函数类型,如下所示:
typedef void func_t(int);
在声明该类型的变量时,您需要使用指针语法:
func_t *fp = foo;
然而,这是与指针相关的语法结束的地方:在声明之后,你完全按照操作基元的方式操作指针:
void foo(int x) { printf("foo says: x=%d\n", x);}
void bar(int x) { printf("bar says: x=%d\n", x);}
int main(void) {
func_t *fp = foo;
fp(5);
fp = bar;
fp(3);
return 0;
}
请注意该语言如何让您bar
完全按照fp
的方式分配int
,即不使用&
运算符。另请注意fp
的呼叫如何不需要星号。
答案 2 :(得分:0)
首先,让我们回想一下指针究竟是什么:指针是内存中某些东西的地址。随着数字存储和高级编程语言的出现,我们得到的结论是代码的数字表示与存储器的数字表示(即存储中的二进制)相同。
旁注:这是现代世界中许多安全问题的原因。例如,SQL注入是一个被视为代码的内存实例,因为计算机无法区分它。
那么,为什么函数指针?因为函数只是计算机视为代码的一块内存。当你调用一个函数时,你所做的只是告诉处理器将其执行移动到该函数在内存中的位置。
你能设计出一种特定于功能的类型吗?当然,但在一天结束时,所有类型都是内存中函数的地址,我们已经有了一个描述内存地址的类型。