尝试创建一个简单的函数来查找字符串中的单个字符"就像strchr()那样",我做了以下内容:
char* findchar(char* str, char c)
{
char* position = NULL;
int i = 0;
for(i = 0; str[i]!='\0';i++)
{
if(str[i] == c)
{
position = &str[i];
break;
}
}
return position;
}
到目前为止它的确有效。但是,当我看到strchr()的原型时:
char *strchr(const char *str, int c);
第二个参数是int?我很想知道..为什么不是炭?这是否意味着我们可以使用int来存储字符,就像我们使用char一样?
这让我想到了第二个问题,我试图改变我的功能以接受一个int作为第二个参数......但是我不确定这样做是否正确和安全:
char* findchar(char* str, int c)
{
char* position = NULL;
int i = 0;
for(i = 0; str[i]!='\0';i++)
{
if(str[i] == c) //Specifically, is this line correct? Can we test an int against a char?
{
position = &str[i];
break;
}
}
return position;
}
答案 0 :(得分:6)
在ANSI C89之前,声明的函数没有原型。当时strchr
的声明看起来像这样:
char *strchr();
那就是它。根本没有声明参数。相反,有这些简单的规则:
int
的所有整数值都将转换为int
double
所以当你打电话给strchr
时,真正发生的是:
strchr(str, (int)chr);
引入ANSI C89时,必须保持向后兼容性。因此,它将strchr
的原型定义为:
char *strchr(const char *str, int chr);
这会保留上述示例调用的确切行为,包括转换为int
。这很重要,因为实现可能会定义传递char
参数的工作方式与传递int
参数不同,这在8位平台上是有意义的。
答案 1 :(得分:5)
考虑fgetc()
的返回值,unsigned char
和EOF
范围内的值,某些负值。这是传递给strchr()
的值。
@Roland Illig对导致int ch
与strchr()
一起使用的历史记录进行了非常好的解释。
OP的代码失败/有以下问题。
1)char* str
被视为unsigned char *str
符合§7.23.1.13
对于本子条款中的所有函数,每个字符都应被解释为具有unsigned char类型
2)i
应为size_t
,以处理字符数组的整个范围。
3)出于strchr()
的目的,空字符被视为搜索的一部分。
终止空字符被认为是字符串的一部分。
4)最好使用const
,str
不会更改。
char* findchar(const char* str, int c) {
const char* position = NULL;
size_t i = 0;
for(i = 0; ;i++) {
if((unsigned char) str[i] == c) {
position = &str[i];
break;
}
if (str[i]=='\0') break;
}
return (char *) position;
}
更多细节
strchr
函数在c
指向的字符串中定位char
(转换为s
)的第一个匹配项。 C11dr§7.23.5.22
所以int c
被视为char
。这可能意味着
if((unsigned char) str[i] == (char) c) {
但我认为这意味着:
if((unsigned char) str[i] == (unsigned char)(char) c) {
或只是
if((unsigned char) str[i] == (unsigned char)c) {