You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自定义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

原因分析

  1. 标准库memcmp的返回值规则:C语言标准仅规定memcmp的返回值需满足:

    • 若第一块内存小于第二块,返回值小于0
    • 若相等,返回0
    • 若第一块大于第二块,返回值大于0
      并没有强制要求返回-1、0、1这三个固定值。实际系统库的memcmp为了性能,通常会用汇编实现(比如x86平台的cmpsb指令),可能直接返回第一个不同字节的差值(或差值的符号相关值),而非固定的-1/1。你参考的是简化的C语言实现,并非实际系统库的真实实现。
  2. 自定义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个字节的对比,这会导致部分场景下提前终止比较,结果错误。
  3. 测试结果的混淆:从测试输出看,你的自定义函数返回的是字符差值(如-63、+58),但你贴出的ft_memcmp代码返回的是-1/1,这说明你实际运行的代码与贴出的版本不一致,可能是代码更新后未同步。

内容的提问来源于stack exchange,提问作者Fernando Loula

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 17:15:53