C - 为什么 while(*s++ == *t++) 不能比较两个字符串



>我正在实现strcmp(char *s, char *t),它通过比较两个字符串之间不同的拳头值来实现<0,如果s<t,则返回0,s>t如果s==t,则返回>0。

通过分离后缀增量和关系等于运算符来实现:

for (; *s==*t; s++, t++)
if (*s=='')
return 0;
return *s - *t;

但是,将后缀增量和关系等于运算符分组不起作用(如下所示):

while (*s++ == *t++)
if (*s=='')
return 0;
return *s - *t;

后者始终返回 0。我认为这可能是因为我们过早地增加了指针,但即使索引 5/10 处出现的两个字符串存在差异,仍然会产生相同的结果。

示例输入:strcomp("hello world", "hello xorld");

返回值:0

我的预感是这是因为运算符优先级,但我并不肯定,如果是这样,我无法准确指出原因。

谢谢你的时间!

因为在for循环中,如果条件(在您的情况下*s==*t)为假,则不会调用增量(在您的情况下s++, t++)。但是在你的while循环中,在这种情况下也会调用增量,所以对于strcomp("hello world", "hello xorld"),两个指针最终都指向字符串中的os。

由于您在测试中总是递增st,因此在字符串相等的情况下,您应该参考终止s[-1],如果字符串不同,则应参考s[-1]t[-1]

另请注意,顺序由比较确定为unsigned char

这是一个修改版本:

int strcmp(const char *s, const char *t) {
while (*s++ == *t++) {
if (s[-1] == '')
return 0;
}
return (unsigned char)s[-1] - (unsigned char)t[-1];
}

根据 LLchux的评论,这里有一个完全符合的反常架构的实现,具有非二进制补码表示和/或CHAR_MAX > INT_MAX

int strcmp(const char *s0, const char *t0) {
const unsigned char *s = (const unsigned char *)s0;
const unsigned char *t = (const unsigned char *)t0;
while (*s++ == *t++) {
if (s[-1] == '')
return 0;
}
return (s[-1] > t[-1]) - (s[-1] < t[-1]);
}

每个人都给出了正确的建议,但仍然天生在比较表达式中内联这些增量运算符,并做了 1 件奇怪的事情。

以下内容感觉更简单,更容易阅读。任何指针都不会递增或递减到无效地址。

while ((*s == *t) && *s)
{
s++;
t++;
}
return *s - *t;

为了完整性,除了已经很好地回答了减法过程中的错误偏移量:

*s, *t为负数时,*s - *t;不正确。

标准 C 库指定字符串函数的比较就像charunsigned char一样。 因此,当字符为负数时,通过char *减去的代码会给出错误的答案。

对于此子句中的所有函数,每个字符都应解释为具有类型unsigned char(因此每个可能的对象表示都是有效的并且具有不同的值)。 C17DR § 7.24.1 3

int strcmp(const char *s, const char *t) {
const unsigned char *us = (const unsigned char *) s;
const unsigned char *ut = (const unsigned char *) t;
while (*us == *ut && *us) {
us++;
ut++;
}
return (*us > *ut) - (*us < *ut);
}

该代码还解决了非 2 的补码访问 -0 和char范围超过int的模糊问题。

最新更新