**已关闭。**此问题为not reproducible or was caused by typos。目前不接受回答。
这个问题是由错字或无法再重现的问题引起的。虽然类似的问题在这里可能是on-topic,但这个问题的解决方式不太可能帮助未来的读者。
23天前关闭
Improve this question的
我写了一个函数来模拟memcmp
,在测试过程中我意识到memcmp
有一些不寻常的地方。库函数的源代码应该是:
#include <ansidecl.h>
#include <stddef.h>
int
memcmp(const void *str1, const void *str2, size_t count)
{
register const unsigned char *s1 = (const unsigned char *)str1;
register const unsigned char *s2 = (const unsigned char *)str2;
while (count-- > 0)
{
if (*s1++ != *s2++)
return s1[-1] < s2[-1] ? -1 : 1;
}
return 0;
}
字符串
我的是
#include <stddef.h>
int ft_memcmp(const void *s1, const void *s2, size_t n)
{
size_t i;
i = 0;
if (n == 0)
return (0);
while(((char *)s1)[i] == ((char *)s2)[i])
{
if ((((char *)s1)[i] == '\0') || (i == (n - 1)))
{
return (0);
}
i++;
}
if (((char *)s1)[i] < ((char *)s2)[i])
return (-1);
else
return (1);
}
型
意外的问题是,根据提供的计数,memcmp
函数开始返回的不是1
或-1
,而是与字符的实际差值,即s1[-1] - s2[-2]
有谁知道这是怎么回事吗?
这是我运行的测试,
int main() {
char *test_strings1[] = { "fdjkDKDJFLDkjdfkjdf", "-456", "ALO marciano!!!", "xc42:", " 7894545989828547", " +99", "abc123", "12abc", "" };
char *test_strings2[] = { "fdjkDKDJFLDSkjdfkjdf", "-456", "ALO_ALO marciano!!!", "xc42", " 789454598982854752", " +99", "abc123", "12abc", "" };
for (int count = 0; count < 50; count++)
for (int string = 0; string < 9; string++) {
int ft = ft_memcmp(test_strings1[string], test_strings2[string], count);
int lib = memcmp(test_strings1[string], test_strings2[string], count);
if (ft != lib) {
printf("******Wrong!!! lib %i ft %i count = %i string = %i*********\n", lib, ft, count, string);
}
}
return 0;
}
型
GCC版本是
gcc --version
Ubuntu clang version 12.0.0-3ubuntu1~20.04.5
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
型
我的系统是Ubuntu 20.04.5 LTS,英特尔®酷睿™ i5- 7360 U CPU@2.30 GHz × 4,梅萨英特尔®虹膜(R)加图形640(Kaby Lake GT3 e)(KBL GT3)
这是我得到的输出,这让我很惊讶。在所有有差异的字符串(索引2,3和4)上,如果count大于7
,memcmp
的行为就会改变(在这个版本的输出中,我的自定义函数返回的是差异,而不是1,-1和0)
Wrong!!! lib -1 ft -63 count = 4 string = 2
Wrong!!! lib -1 ft -23 count = 4 string = 4
Wrong!!! lib -1 ft -63 count = 5 string = 2
Wrong!!! lib +1 ft +58 count = 5 string = 3
Wrong!!! lib -1 ft -23 count = 5 string = 4
Wrong!!! lib -1 ft -63 count = 6 string = 2
Wrong!!! lib +1 ft +58 count = 6 string = 3
Wrong!!! lib -1 ft -23 count = 6 string = 4
Wrong!!! lib -1 ft -63 count = 7 string = 2
Wrong!!! lib +1 ft +58 count = 7 string = 3
Wrong!!! lib -1 ft -23 count = 7 string = 4
型
3条答案
按热度按时间7gyucuyw1#
来自C标准(7.24.4.1 memcmp函数)
返回
3**memcmp函数返回一个大于、等于或小于零的整数,**相应地,s1指向的对象大于、等于或小于s2指向的对象。
yhqotfr82#
C标准(C2x)规定:
7.26.4比较功能
比较函数
memcmp
、strcmp
和strncmp
返回的非零值的符号由第一对字符(均解释为unsigned char
)的值之间的差的符号确定,这两个字符在被比较的对象中不同。[...]
memcmp
函数返回一个大于、等于或小于零的整数,相应地,s1
指向的对象大于、等于或小于s2
指向的对象。memcmp
的发布代码只是一个可能的实现。C标准没有为不同内容的块指定确切的返回值,只是返回值的符号。因此返回s1[-1] - s2[-1]
与返回s1[-1] < s2[-1] ? -1 : 1
或1 - 2 * (s1[-1] < s2[-1])
一样符合要求还请注意,您的实现存在问题:
((char *)s1)[i] == '\0')
是没有意义的,因为memcmp
不会在任何空终止符上停止。char
值进行比较是不正确的:C标准规定必须使用unsigned char
值进行比较。以下是修改后的版本:
字符串
main
函数不正确:ft
和lib
都不为零,则必须检查它们的符号是否匹配。count
不应该超过对象的大小。这解释了为什么对于相同的字符串,当count
大于7
时,会得到不一致的结果:前8个字节或相同字符串之外的内存内容不同。阅读字符串末尾之外的字节(即:空终止符之后)无论如何都有未定义的行为。以下是修改后的版本:
型
az31mfrm3#
原始函数(非常简化)是:
字符串