为什么strchr需要一个int才能找到char?

时间:2010-03-06 20:28:13

标签: c string char int

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作为参数?

3 个答案:

答案 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参数声明它是不正确的。

因此,您永远不会看到期望charcharshort类型参数的“传统”标准库函数。所有这些函数都将使用floatint类型的参数声明。

标准保证的基本原理是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库中函数的声明。