我想知道,当我们创建函数时
int compar(const void *, const void *)
qsort
我们只是将其名称传递给and的参数之一bsearch
,这些函数如何识别所说的基本上随机的词(因为我们从未明确声明它是函数指针,而是实际函数)并将其用作参数?qsort
在and的函数声明中是否有显式转换bsearch
?
我想知道,当我们创建函数时
int compar(const void *, const void *)
qsort
我们只是将其名称传递给and的参数之一bsearch
,这些函数如何识别所说的基本上随机的词(因为我们从未明确声明它是函数指针,而是实际函数)并将其用作参数?qsort
在and的函数声明中是否有显式转换bsearch
?
qsort
这与and函数本身无关bsearch
,而是函数名称由编译器隐式转换为根据标准的函数指针,C11 6.3.2.1 Language / Conversions / Other operands / Lvalues, arrays, and function designators
:
函数指示符是具有函数类型的表达式。除非它是 sizeof 运算符、_Alignof 运算符或一元 & 运算符的操作数,否则“函数返回类型”类型的函数指示符将转换为“指向函数返回类型的指针”类型的表达式。
这意味着,当您传递compar
给qsort()
(例如)时,传递的是指向函数的实际指针,而不是一些“基本上随机的词”。
隐含地将函数标识符视为其地址的原因在很久以前就存在了,但是(这整个部分是我的假设,基于我想考虑的智能推理,但绝不是确定的)它很可能因为函数的值没有意义。使用 identifier int i = 5;
,它有一个值 (5),您也可以使用&i
它来获取它的地址。
但是,对于函数,它们实际上并没有这样的值。你可以调用它们来生成一个值,xyzzy()
你可以获取它们的地址&xyzzy
,以便以后通过函数指针调用。
但是它们没有像整数那样与地址分开的真正内在价值i
。所以早期的编译器(pre-ANSI)只允许简写xyzzy
为&xyzzy
. 当然,由于 ANSI 最初的任务是编纂现有实践而不是创建一种新语言,因此他们保留了这种行为。
如果 K&R 采取了另一种方式并决定xyzzy
应该调用不传递参数的函数,就像 一样xyzzy()
,世界将是一个不同的地方:-)