为什么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样式定义),它将被隐式转换回char
types,并在函数中用作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为char
, short
或float
。 所有这些函数将用int
或double
types的参数声明。
一个非常相同的原理背后的标准保证char指针和void *
指针共享相同的表示和alignment要求。 依靠这个保证,你可以声明malloc
为void *
-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'是int
types的。
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 conversion
的multi-character character constant