为什么 strchr 采用 int 来查找 char?
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
作为参数呢?
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;
}
Does anyone know why? Why not just take a char
as a parameter?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
其原因纯粹是历史原因。请注意,在过去的 C 语言(K&RC)中,没有函数原型这样的东西。那时的 strchr 函数将被声明为
K&R 风格并定义为
然而,在 C 语言中(在 K&RC 和现代语言中),如果该函数声明时没有原型(如上所示),每个函数调用中传递的参数都会受到所谓的默认参数提升。在默认参数提升下,任何小于
int
(或unsigned int
)的整数类型始终转换为int
(或unsigned int
)代码>)。即当参数未声明时,每当您传递char
值作为参数时,该值都会隐式转换为int
,并且实际上以物理方式传递作为一个int
。short
也是如此。 (顺便说一句,float
通过默认参数提升转换为double
)。如果在函数内部参数实际上被声明为char
(如上面的 K&R 样式定义中所示),则它会隐式转换回char
code> 类型并在函数内用作char
。这就是它在 K&R 时代的工作原理,实际上这也是它在现代 C 语言中的工作原理,当函数没有原型或使用可变参数时。现在,在现代 C 中提示,它具有函数原型并使用现代风格的函数定义语法。为了保留和重现
strchr
的“传统”功能,如上所述,我们别无选择,只能将strchr
的参数声明为int
并在函数内将其显式转换为char
。这正是您在引用的代码中观察到的。这与标准中描述的strchr
功能完全相同。此外,如果您有一个已经编译的遗留库,其中
strchr
是按照 K&R 风格定义的,如上所示,并且您决定为该库提供现代原型,则的正确声明strchr
是因为
int
是上述遗留实现期望以c
形式物理接收的内容。使用char
参数声明它是不正确的。因此,您永远不会看到“传统”标准库函数需要
char
、short
或float
类型的参数。所有这些函数都将使用int
或double
类型的参数来声明。char 指针和 void * 指针共享相同的表示和对齐要求的标准保证背后有一个非常相同的基本原理。依靠此保证,您可以将
malloc
声明为void *
返回函数,然后将此声明与标准库的预编译遗留版本一起使用,其中malloc< /code> 实际上返回了
char *
。参考:C99基本原理,版本5.10
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 asand defined in K&R style as
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
(orunsigned int
) is always converted toint
(orunsigned int
). I.e. when the parameters are undeclared, whenever you pass achar
value as an argument, this value is implicitly converted toint
, and actually physically passed as anint
. The same is true forshort
. (BTW,float
is converted todouble
by default argument promotions). If inside the function the parameter is actually declared as achar
(as in the K&R style definition above), it is implicitly converted back tochar
type and used as achar
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.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 ofstrchr
as anint
and explicitly convert it tochar
inside the function. This is exactly what you observe in the code you quoted. This is exactly as the functionality ofstrchr
is described in the standard.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 forstrchr
would bebecause
int
is what the above legacy implementation expects to physically receive asc
. Declaring it with achar
parameter would be incorrect.For this reason, you will never see "traditional" standard library functions expecting parameters of type
char
,short
orfloat
. All these functions will be declared with parameters of typeint
ordouble
instead.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 declaremalloc
as avoid *
-returning function and then use this declaration with a pre-compiled legacy version of standard library wheremalloc
actually returnedchar *
.Reference: the C99 rationale, version 5.10
我想这只能归咎于历史的偶然。您说得完全正确,
char
似乎是用于搜索字符的明显数据类型。在 C 库中的某些情况下,例如 getc() 函数,会为从输入读取的字符返回一个 int 值。这不是
char
,因为可以返回额外的非字符值(EOF
,通常为 -1)来指示字符流的结尾。EOF
情况不适用于strchr()
函数,但他们现在无法真正返回并更改 C 库中函数的声明。I think this can be attributed to nothing more than an accident of history. You're exactly right that
char
seems the obvious data type to use for the character being searched for.In some situations in the C library, such as the
getc()
function, anint
value is returned for the character read from input. This is not achar
because an extra non-character value (EOF
, usually -1) can be returned to indicate the end of the character stream.The
EOF
case doesn't apply to thestrchr()
function, but they can't really go back and change the declaration of the function in the C library now.在c 中,字符文字的类型是
int
。例如:“a”的类型为int
。In c the type of a character literal is
int
. For example: 'a' is of typeint
.int c
是您要搜索的字符。字符作为整数传递,但实际上只搜索低 8 位。因此,应该将其移交给 charstrchr
函数如下所示:正如您所看到的,有
int c
的cast
到strchr
。代码>(char)c。现在回答您的问题,您的
char ch
它被转换为整数int c
并用作字符的序数值。所以下面的程序应该没问题:
但是下面的程序不行:
因为
多字符字符常量
,这是隐式常量转换中的溢出
int c
is the character that you want to search. The character is passed as an integer, but in fact only the lower 8 bits are searched. It should therefore be handed over to a charThe
strchr
function looks like this:As you can see there is a
cast
ofint c
to(char)c
.Now to Answer to your question, your
char ch
it is converted to an integerint c
and applied as the ordinal value of a character.So the following program should be OK:
But the following not:
Because of
multi-character character constant
which isoverflow in implicit constant conversion