为什么strchr需要一个int来findchar?

C标准库中的strchr函数在一个string中查找char ,但是其签名对于search字符采用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作为参数?

原因纯粹是历史的。 请注意,在C语言(K&R C)的旧版本中,没有函数原型这样的东西。 在那些时候strchr函数将被声明为

 char *strchr(); 

并在K&R风格中定义为

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

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

现在,在具有函数原型并使用现代风格函数定义语法的现代C中提示。 为了保留和重现strchr的“传统”function,如上所述,我们别无select,只能将strchr的参数声明为int并在函数内将其明确地转换为char 。 这正是你所引用的代码中所观察到的。 这与标准中描述的strchr的function完全相同。

而且,如果你有一个已经编译好的遗留库,在上面显示的K&R风格中定义了strchr ,并且你决定为这个库提供现代化的原型,那么strchr的正确声明应该是

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

因为int是上面的遗留实现期望实际接收的c 。 用char参数声明它将是不正确的。

由于这个原因,你永远不会看到“传统的”标准库函数需要types为charshortfloat 。 所有这些函数将用intdoubletypes的参数声明。

一个非常相同的原理背后的标准保证char指针和void *指针共享相同的表示和alignment要求。 依靠这个保证,你可以声明mallocvoid * -returning函数,然后用这个声明和预编译的标准库的旧版本, malloc实际上返回char *


参考:C99的理由,版本5.10

7.1.4使用库函数
/ – /
所有的库原型都是用“扩展”types来指定的:以前声明为char的参数现在被写为int。 这确保了大多数库函数可以在范围内有或没有原型被调用,从而保持与C89之前的代码的向后兼容性

我认为这可以归因于历史事故。 你是完全正确的, char似乎是明显的数据types用于search字符。

在C库中的某些情况下,例如getc()函数,会为从input读取的字符返回一个int值。 这不是一个char因为可以返回一个额外的非字符值( EOF ,通常为-1)来指示字符stream的结束。

EOF情况并不适用于strchr()函数,但是现在不能真正返回并更改C库中函数的声明。

在c中,字符文字的types是int 。 例如:'a'是inttypes的。

int c是你想要search的字符。 字符作为整数传递,但实际上只search低8位。 因此应该交给char

strchr函数如下所示:

 char *strchr(const char *s, int c){ while (*s != (char)c) if (!*s++) return 0; return (char *)s; } 

正如你所看到的,有一个int c(char)c

现在回答你的问题,你的char ch被转换为一个整数int c并作为字符的序数值应用。

所以下面的程序应该是OK的:

 #include<stdio.h> #include<string.h> int main(void){ char *name = "Michi"; int c = 99; /* 99 is the ANSCI code of c*/ char *ret = strchr(name, c); printf("String after %s\n", ret); return 0; } 

但以下不是:

 #include<stdio.h> #include<string.h> int main(void){ char *name = "Michi"; char c = '99'; /* 99 is the ANSCI code of c*/ char *ret = strchr(name, c); printf("String after %s\n", ret); return 0; } 

由于overflow in implicit constant conversionmulti-character character constant