C标准库中的strchr
函数在字符串中查找char
,但其签名对搜索字符采用int
。在我发现的这两个实现中,实现将此int
强制转换为char
:
char *strchr(const char *s, int c) {
while (*s != (char)c)
if (!*s++)
return 0;
return (char *)s;
}
char *strchr(const char *s, int c) {
while (*s && *s != (char)c)
s++;
if (*s == c)
return (char *)s;
return NULL;
}
有谁知道为什么?为什么不把char
作为参数?
答案 0 :(得分:37)
原因纯粹是历史性的。注意,在C语言(K& R C)的旧时代,没有函数原型这样的东西。这些时间的strchr
函数将被声明为
char *strchr();
并以K& R样式定义为
char *strchr(s, c)
char *s;
char c;
{
/* whatever */
}
然而,在C语言中(在K& RC和现代语言中)如果声明函数没有原型(如上所示),则在每个函数调用中传递的参数都会被称为默认参数促销。在默认参数促销下,任何小于int
(或unsigned int
)的整数类型始终会转换为int
(或unsigned int
)。即当参数未声明时,每当您传递char
值作为参数时,此值隐式转换为int
,并实际上作为int
实际传递。 short
也是如此。 (顺便说一句,float
通过默认参数提升转换为double
。如果在函数内部,参数实际上被声明为char
(如上面的K& R样式定义),则隐式转换回char
类型并用作函数内部char
。这就是它在K& R时代的工作方式,这实际上是它在现代C中的工作方式,当函数没有原型或使用可变参数时。
现在,在现代C中提示,它具有函数原型并使用现代风格的函数定义语法。为了保留和重现strchr
的“传统”功能,如上所述,我们别无选择,只能将strchr
的参数声明为int
,并明确将其转换为函数内部char
。这正是您在引用的代码中观察到的内容。这正如标准中描述的strchr
的功能一样。
此外,如果您有一个已编译的遗留库,其中strchr
以K& R样式定义,如上所示,并且您决定为该库提供现代原型,{{1将是
strchr
因为char *strchr(const char *s, int c);
是上述旧版实现期望实际接收为int
的内容。用c
参数声明它是不正确的。
因此,您永远不会看到期望char
,char
或short
类型参数的“传统”标准库函数。所有这些函数都将使用float
或int
类型的参数声明。
标准保证的基本原理是char指针和double
指针共享相同的表示和对齐要求。依靠此保证,您可以将void *
声明为malloc
- 返回函数,然后将此声明与标准库的预编译旧版本一起使用,其中void *
实际返回malloc
参考:C99基本原理,版本5.10
7.1.4库函数的使用
/ - /
所有库原型都是根据“加宽”类型指定的: 以前声明为char的参数现在写为int。这个 确保可以使用或不使用a调用大多数库函数 范围内的原型,从而保持向后兼容性 前C89代码
答案 1 :(得分:3)
在c中,字符文字的类型为int
。例如:'a'的类型为int
。
答案 2 :(得分:3)
我认为这可以归结为历史事故。你完全正确char
似乎是用于搜索字符的明显数据类型。
在C库的某些情况下,例如getc()
函数,从输入中读取的字符将返回int
值。这不是char
,因为可以返回额外的非字符值(EOF
,通常为-1)以指示字符流的结束。
EOF
案例不适用于strchr()
函数,但它们现在无法返回并更改C库中函数的声明。