为什么 strchr 需要一个 int 才能找到 char? [英] Why does strchr take an int for the char to be found?

查看:6
本文介绍了为什么 strchr 需要一个 int 才能找到 char?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

C 标准库中的 strchr 函数在字符串中查找 char,但其签名采用 int 作为搜索字符.在我发现的这两个实现中,实现将此 int 转换为 char:

The strchr function in the C standard library looks for a char in a string, but its signature takes an int for the search character. In these two implementations I found, the implementation casts this int to a 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 作为参数?

Does anyone know why? Why not just take a char as a parameter?

推荐答案

原因纯属历史原因.请注意,在过去的 C 语言 (K&R C) 中,没有 函数原型 这样的东西.那个时候的 strchr 函数将被声明为

The reasons for that are purely historical. Note, that in the old days of C language (K&R C) there was no such thing as function prototype. A strchr function in those times would be declared as

char *strchr();

并以 K&R 风格定义为

and defined in K&R style as

char *strchr(s, c)
  char *s;
  char c;
{
  /* whatever */
}

但是,在 C 语言中(在 K&RC 和现代语言中也是如此)如果函数声明时没有原型(如上所示),则在每个函数调用中传递的参数都会受到所谓的 默认参数提升.在默认参数提升下,任何小于 int(或 unsigned int)的整数类型总是转换为 int(或 unsigned int).IE.当参数未声明时,每当您将 char 值作为参数传递时,该值会隐式转换为 int,并且实际上以物理方式传递int.short 也是如此.(顺便说一句,默认参数提升将 float 转换为 double).如果在函数内部,参数实际上被声明为 char(如上面的 K&R 样式定义),它会隐式转换回 char 类型并在函数内用作 char.这就是它在 K&R 时代的工作方式,而在现代 C 语言中,当函数没有原型或使用可变参数时,这实际上也是如此.

However, in C language (in K&R C and in the modern one as well) if the function is declared without a prototype (as shown above), the parameters passed in each function call are subjected to so called default argument promotions. Under default argument promotions any integral type smaller than int (or unsigned int) is always converted to int (or unsigned int). I.e. when the parameters are undeclared, whenever you pass a char value as an argument, this value is implicitly converted to int, and actually physically passed as an int. The same is true for short. (BTW, float is converted to double by default argument promotions). If inside the function the parameter is actually declared as a char (as in the K&R style definition above), it is implicitly converted back to char type and used as a char inside the function. This is how it worked in K&R times, and this actually is how it works to this day in modern C when function has no prototype or when variadic parameters are used.

现在,提示现代 C,它具有 函数原型 并使用现代风格的函数定义语法.为了保留和重现 strchr 的传统"功能,如上所述,我们别无选择,只能将 strchr 的参数声明为 int 并将其显式转换为函数内部的 char.这正是您在引用的代码中观察到的.这与标准中描述的 strchr 的功能完全相同.

Now, cue in the modern C, which has function prototypes and uses modern-style function definition syntax. In order to preserve and reproduce the "traditional" functionality of strchr, as described above, we have no other choice but to declare the parameter of strchr as an int and explicitly convert it to char inside the function. This is exactly what you observe in the code you quoted. This is exactly as the functionality of strchr is described in the standard.

此外,如果您有一个已编译的遗留库,其中 strchr 以 K&R 样式定义,如上所示,并且您决定为该库提供现代原型,则正确声明strchr 将是

Moreover, if you have an already-compiled legacy library, where strchr is defined in K&R style as shown above, and you decided to provide modern prototypes for that library, the proper declaration for strchr would be

char *strchr(const char *s, int c);

因为 int 是上述遗留实现期望物理接收为 c 的内容.用 char 参数声明它是不正确的.

because int is what the above legacy implementation expects to physically receive as c. Declaring it with a char parameter would be incorrect.

因此,您永远不会看到需要 charshortfloat 类型参数的传统"标准库函数.所有这些函数都将使用 intdouble 类型的参数声明.

For this reason, you will never see "traditional" standard library functions expecting parameters of type char, short or float. All these functions will be declared with parameters of type int or double instead.

标准保证 char 指针和 void * 指针共享相同的表示和对齐要求的背后有一个非常相同的理由.依靠此保证,您可以将 malloc 声明为返回 void * 的函数,然后将此声明与标准库的预编译旧版本一起使用,其中 malloc 实际上返回了 char *.

A very same rationale is behind the standard guarantee that char pointers and void * pointers share the same representation and alignment requirements. Relying on this guarantee you can declare malloc as a void *-returning function and then use this declaration with a pre-compiled legacy version of standard library where malloc actually returned char *.

参考:C99 基本原理,5.10 版

Reference: the C99 rationale, version 5.10

7.1.4 库函数的使用
/--/
所有库原型都是根据扩展"类型指定的:以前声明为 char 的参数现在写为 int.这确保大多数库函数可以在有或没有范围内的原型,从而保持向后兼容性C89 之前的代码

7.1.4 Use of library functions
/--/
All library prototypes are specified in terms of the "widened" types: an argument formerly declared as char is now written as int. This ensures that most library functions can be called with or without a prototype in scope, thus maintaining backwards compatibility with pre-C89 code

这篇关于为什么 strchr 需要一个 int 才能找到 char?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆