在C语言中循环遍历字符数组

4

我并不是一名C开发人员,也不太了解C语言,但我遇到了这样一个面试问题:

int toto(char *a, char *b){
    while(*a++ == *b++);
    return(*a == 0 && *b == 0);
}

我花了很多时间来试图理解它,阅读了一些在线资料后,我有点明白它试图做什么,但仍然存在一些奇怪的行为。 据我所知(如果我错了,请纠正我),此代码段将遍历两个字符串(字符数组),并确定它们是否相等,直到最后一个字符,并仅在最后一个字符不同的情况下返回true。return (*a == 0 && *b == 0) 检查所有以 C 结尾的字符串中的整数0。这仅发生在循环退出之后,即当两个字符在增量发生之前不相等时。因此,如果最后两个字符不相等,则将它们递增为 0 int 并继续执行 return 语句。我还注意到,如果字符串差异为1,则如果字符串相等直到 n-1,它仍会返回true,例如:
char a[] = "ggr"
char b[] = "ggre"
//returns 1
char a[] = "ggr"
char b[] = "ggf"
//returns 1

我发现这种行为很奇怪,但我不理解的测试用例如下:

char a[] = "abcd";
char b[] = "abcd";
//returns 1
char a[] = "abc"
char b[] = "abc"
//returns 0

我理解为什么abc返回false,但是我不知道为什么abcd没有返回相同的结果。对我来说,它似乎会区分不同长度的字符串,但代码似乎并不关心长度。
有人能解释一下这段代码想要做什么以及为什么在给定不同长度的字符串时行为不同吗?我感觉这与某些运算符的优先级有关,但我找不到答案。
编辑:看起来面试提供的代码是故意有缺陷的,我原本以为这段代码是有效的。

1
这段代码太糟糕了。 - Mad Physicist
那个循环后的检查基本上每次都会出现未定义的操作。 - Mad Physicist
使用调试器或纸笔逐步检查测试用例。这不是魔法。 - Mad Physicist
2个回答

8

你的代码存在未定义行为。它最终将访问超出以null结尾的char数组的内存。从这个意义上说,这段代码是错误的。

正确的实现应该类似于:

int toto(char *a, char *b){
    while(*a && *b && *a == *b) a++,b++;
    return (*a - *b)?0:1;
}

4

因为它存在一个错误。如果两个字符串在某个位置完全相同,那么你将会迭代超过字符串的结尾。这将导致未定义的行为,意味着有时可能正常工作,而有时可能会崩溃(或执行其他各种操作)。考虑将以下代码添加到您的函数中:

int counter = 0;
while(*a++ == *b++) {
    printf("Count %d\n", ++counter);
}

实时示例

您将注意到,它可以打印:

Count 1
Count 2
Count 3
Count 4

这意味着你的返回行 (return(*a == 0 && *b == 0);) 将会越过字符串的末尾 (即第5个字符) 进行解引用。

完全相等或最后一个字符不同。增量是无条件的。 - Mad Physicist
@MadPhysicist 直到两个字符串的结尾完全相等为止。 - Fantastic Mr Fox

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接