其原因纯粹是历史原因。请注意,在过去的 C 语言 (K&R C) 中,没有这样的东西函数原型. A strchr
那时的函数将被声明为
char *strchr();
并以 K&R 风格定义为
char *strchr(s, c)
char *s;
char c;
{
/* whatever */
}
然而,在 C 语言中(在 K&R C 和现代 C 语言中),如果函数声明时没有原型(如上所示),则每个函数调用中传递的参数都会受到所谓的默认参数促销。在默认参数提升下,任何小于的整数类型int
(or unsigned int
) 总是转换为int
(or unsigned int
)。 IE。当参数未声明时,每当您传递char
value 作为参数,这个值是隐含地转换成int
,并且实际上作为int
。对于short
. (BTW, float
被转换为double
默认参数促销)。如果在函数内部参数实际上被声明为char
(如上面的 K&R 风格定义),它是隐含地转换回char
类型并用作char
函数内部。这就是它在 K&R 时代的工作原理,实际上这也是它在现代 C 语言中的工作原理,当函数没有原型或使用可变参数时。
现在,提示现代 C,它有函数原型并使用现代风格的函数定义语法。为了保留和再现“传统”功能strchr
,如上所述,我们别无选择,只能声明参数strchr
as an int
并将其显式转换为char
函数内部。这正是您在引用的代码中观察到的。这与功能完全相同strchr
标准中有描述。
此外,如果您有一个已经编译的遗留库,其中strchr
以 K&R 风格定义,如上所示,并且您决定为该库提供现代原型,正确的声明strchr
将会
char *strchr(const char *s, int c);
because int
是上述遗留实现期望物理接收的内容c
。用 a 来声明它char
参数将不正确。
因此,您永远不会看到“传统”标准库函数需要以下类型的参数char
, short
or float
。所有这些函数都将使用类型参数进行声明int
or double
反而。
char 指针和 char 指针的标准保证背后的基本原理完全相同void *
指针具有相同的表示和对齐要求。依靠此保证,您可以声明malloc
as a void *
-返回函数,然后将此声明与标准库的预编译遗留版本一起使用,其中malloc
实际上返回了char *
.
参考:C99基本原理,版本5.10
7.1.4 库函数的使用
/--/
所有库原型都是根据“扩展”类型指定的:
以前声明为 char 的参数现在写为 int。这
确保大多数库函数都可以使用或不使用
范围内的原型,从而保持向后兼容性
C89 之前的代码