自定义memcmp实现与库函数返回值不符问题排查
memcmp与自定义ft_memcmp返回值不一致问题解析
问题描述
我实现了模拟标准库memcmp的ft_memcmp函数,测试时发现系统库的memcmp并非始终返回1、-1或0,部分场景下会返回字符的实际差值,导致和自定义函数结果不一致。以下是相关代码、测试用例及环境信息,求解原因。
库函数参考实现
#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; }
自定义ft_memcmp实现
#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); }
测试用例
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; }
运行环境
- 编译器版本: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
- 硬件:Intel® Core™ i5-7360U CPU @ 2.30GHz × 4,Mesa Intel® Iris(R) Plus Graphics 640 (Kaby Lake GT3e) (KBL GT3)
测试输出
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
原因分析
标准库memcmp的返回值规则:C语言标准仅规定
memcmp的返回值需满足:- 若第一块内存小于第二块,返回值小于0
- 若相等,返回0
- 若第一块大于第二块,返回值大于0
并没有强制要求返回-1、0、1这三个固定值。实际系统库的memcmp为了性能,通常会用汇编实现(比如x86平台的cmpsb指令),可能直接返回第一个不同字节的差值(或差值的符号相关值),而非固定的-1/1。你参考的是简化的C语言实现,并非实际系统库的真实实现。
自定义ft_memcmp的错误:
- 有符号字符比较:你将
void*转换为char*进行比较,而char在多数系统中是有符号类型。当遇到ASCII值大于127的字符时,会被当作负数处理,导致比较结果与标准memcmp(按无符号字符比较)不一致。比如测试中字符串2的第4个字节,空格(ASCII 32)和下划线(ASCII 95)按有符号比较时差值为32-95=-63,但标准库按无符号比较后返回-1(仅表示小于)。 - 错误的终止符检查:你的循环中判断
((char *)s1)[i] == '\0'时直接返回0,但memcmp的设计是严格比较指定数量的字节,即使遇到空字符也会继续比较,直到完成n个字节的对比,这会导致部分场景下提前终止比较,结果错误。
- 有符号字符比较:你将
测试结果的混淆:从测试输出看,你的自定义函数返回的是字符差值(如-63、+58),但你贴出的
ft_memcmp代码返回的是-1/1,这说明你实际运行的代码与贴出的版本不一致,可能是代码更新后未同步。
内容的提问来源于stack exchange,提问作者Fernando Loula
相关产品推荐
相关产品推荐

