C语言函数_string.h 之 内存comparison函数memcmp

本文详细介绍了memcmp函数的功能、原型、返回值和注意事项,并提供了C语言实现代码及使用示例,帮助开发者正确地使用memcmp函数进行内存比较。

memcmp

原型:

        int memcmp(const void *ptr1, const void*ptr2, unsigned int count);

功能:

        memcmp用于比较内存区域ptr1和ptr2的前count个字节,是按字节进行比较的。

头文件:

        string.h 或 memory.h

返回值:

        < 0 :ptr1和ptr2所指内存中第一个不相等的字节有*((char*)ptr1+x) < *((char*)ptr2+x)
        > 0 :ptr1和ptr2所指内存中第一个不相等的字节有*((char*)ptr1+x) > *((char*)ptr2+x)

        = 0 :ptr1和ptr2所指的内存块中前count个字节都相等

说明:

        1、函数的返回条件是:比较次数达count次或者*((char*)ptr1+x) - *((char*)ptr2+x)的值不为零(即两个块内存中第x字节不相等)。
        2、函数是按字节进行比较的,如果还没有达到上述返回条件,即使遇到'\0'也不会停止比较。而判断规则是按照ASCII码表中字母的顺序进行比较的,即'a'的值为97,'A'的值为65,因此'a'比'A'大。
        3、调用函数时如果参数为结构体,则需要确保结构体中的填充字节被清零。例子:
        typedef struct memcmp_test {
                short data1;
                int data2;
        } memcmp_test_t;
        int main()
        {
                memcmp_test_t test_1 = { 0, 0};
                memcmp_test_t test_2;
                memset( &test_2, 0, sizeof( test_2));
                int judge = memcmp( &test_1, &test_2, sizeof(memcmp_test_t));
                if( 0 == judge)
                        printf("they are equal\n");
                else
                        printf("they are not equal\n");
                return 0;
        }
        在平台windows7 x64上,gcc (GCC) 4.7.2编译后输出结果为: they are equal;
        在平台windows7 x64上,VC++6.0编译运行结果:they are not equal;
        在平台CentOS i386上,gcc(GCC)4.4.7 20120313编译后输出结果为they are not equal;
        解析:出现not equal这种情况,是因为memcmp_test->data1的类型是short而data2的类型是int,由结构体对齐规则知道memcpy_test的每个成员需要按4字节进行对齐,也就data1和data2之间还有两个字节的空间,其值理论上是随机数,因此test_1变量中的内存空间的每个字节不一定为0值,而test_2调用memset函数后确保了其填充字节已被清零,因为便会得到: they are not equal的结果。通过上面运行的结果,我的猜想是:不同的编译器及其版本,对结构体填充字节的赋值是不同的,不过把填充字节的值看作是随机值来处理总没坏处。
        因此,对结构体进行比较的时候,不建议使用字节比较函数如memcmp,如果一定要用,应该确定填充字节被清零,否则结果令你猜不到。

memcmp函数的C语言实现代码:

        /*返回值可能为正数,0,负数三种之一,下面实现采用1表示>, 0表示=, -1表示<*/
        int memcmp(const void *ptr1, const void *ptr2, unsigned int count)
        {
                const char *p1=(char*)ptr1, *p2=(char*)ptr2;
                for( /*NULL*/; 0 < count; count --)
                {
                        if( (*p1 - *p2) < 0)
                                return -1;
                        else if( (*p1 - *p2) > 0)
                                return 1;
                        (char*)p1 ++;
                        (char*)p2 ++;
                }
                return 0;
        }
        例程:
        char buffer1[] = "DWgaOtP12df0";
        char buffer2[] = "DWGAOTP12DF0";
        int res = memcmp(buffer1, buffer2, 16);
        printf("%d\n", res);
        输出结果是:1(因为第三个字母g的ASCII比G的要大)

相关函数:

        strcmp

                函数原型: int strcmp( const char *str1, const char *str2);
                功能:比较两个字符串的大小,str1>str2返回正数,str1=str2返回0,str1<str2返回-1

        strncmp

                函数原型:int strncmp( const char *str1, const char *str2, size_t len)
                功能:比较两个字符串的len个字节,返回值和strcmp一样。
帮我添加一个函数,用于对比与memcpy的时间效率: /* * @Description: Unit test for bulk memory copy. * @Author: liruibo.tp-link.com.hk * @Date: 2025-07-16 17:05:04 * @LastEditors: liruibo.tp-link.com.hk * @LastEditTime: 2025-07-31 15:57:35 */ #include "bulk_mem_copy.h" #include <assert.h> #include <stdlib.h> #include <string.h> void test_normal_copy() { const char src[] = "hello world"; char dest[50] = {0}; bulk_mem_copy((unsigned char*)dest, (unsigned char*)src, strlen(src) + 1); assert(0 == strcmp(dest, src)); printf("[PASS] normal copy test.\n"); } void test_zero_length_copy() { int dest = 42; int src = 0; bulk_mem_copy((unsigned char*)&dest, (unsigned char*)&src, 0); assert(42 == dest); printf("[PASS] zero length copy test.\n"); } void test_overlap_copy() { char data[15] = "AAAAABBBBBCCCCC"; bulk_mem_copy((unsigned char*)data + 5, (unsigned char*)data, 10); assert(0 == strcmp(data, "AAAAAAAAAABBBBB")); printf("[PASS] overlap copy test.\n"); } void test_large_block_copy() { const size_t size = 1024 * 1024 * 10; char* src = malloc(size); char* dest = malloc(size); if (NULL == src || NULL == dest) { printf("[ERROR] large block copy test malloc failed.\n"); exit(EXIT_FAILURE); } memset(src, 0xAA, size); bulk_mem_copy((unsigned char*)dest, (unsigned char*)src, size); assert(0 == memcmp(src, dest, size)); free(src); src = NULL; free(dest); dest = NULL; printf("[PASS] large block copy test.\n"); } int main() { printf("STARTING UNIT TESTS...\n"); test_normal_copy(); test_zero_length_copy(); test_overlap_copy(); test_large_block_copy(); printf("ALL TESTS PASSED!\n"); return 0; }
08-01
aarch64-openwrt-linux-gcc -I ../inc -I/home/yzf/host/include/ -g -Wall -DARMFW -c -o cpe_conn.o cpe_conn.c aarch64-openwrt-linux-gcc -I ../inc -I/home/yzf/host/include/ -g -Wall -DARMFW -c -o cpe_epoll.o cpe_epoll.c In file included from cpe_epoll.c:1: /home/yzf/toolchain-aarch64_generic_gcc-12.3.0_musl/include/sys/errno.h:1:2: warning: #warning redirecting incorrect #include <sys/errno.h> to <errno.h> [-Wcpp] 1 | #warning redirecting incorrect #include <sys/errno.h> to <errno.h> | ^~~~~~~ aarch64-openwrt-linux-gcc -I ../inc -I/home/yzf/host/include/ -g -Wall -DARMFW -c -o cpe_fw.o cpe_fw.c cpe_fw.c: In function 'CpeFwRule': cpe_fw.c:46:34: warning: '%d' directive writing between 1 and 3 bytes into a region of size 2 [-Wformat-overflow=] 46 | sprintf(Action, "%d", cpi->rule_table.rule[i].action); | ^~ cpe_fw.c:46:33: note: directive argument in the range [0, 255] 46 | sprintf(Action, "%d", cpi->rule_table.rule[i].action); | ^~~~ cpe_fw.c:46:17: note: 'sprintf' output between 2 and 4 bytes into a destination of size 2 46 | sprintf(Action, "%d", cpi->rule_table.rule[i].action); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ aarch64-openwrt-linux-gcc -I ../inc -I/home/yzf/host/include/ -g -Wall -DARMFW -c -o cpe_http.o cpe_http.c cpe_http.c: In function 'CpeParesHandle': cpe_http.c:61:13: warning: unused variable 'num' [-Wunused-variable] 61 | int num = strstr(mm->resp,"</Root>") - mm->resp; | ^~~ cpe_http.c: In function 'CpeUrlToken': cpe_http.c:287:42: warning: the comparison will always evaluate as 'false' for the address of 'passwd' will never be NULL [-Waddress] 287 | if(CpI->TokenInfo.passwd == NULL) | ^~ In file included from ../inc/cpe_http.h:6, from cpe_http.c:4: ../inc/cpe_main.h:112:14: note: 'passwd' declared here 112 | char passwd[17]; | ^~~~~~ aarch64-openwrt-linux-gcc -I ../inc -I/home/yzf/host/include/ -g -Wall -DARMFW -c -o cpe_main.o cpe_main.c aarch64-openwrt-linux-gcc -I ../inc -I/home/yzf/host/include/ -g -Wall -DARMFW -c -o cpe_sql.o cpe_sql.c aarch64-openwrt-linux-gcc -I ../inc -I/home/yzf/host/include/ -g -Wall -DARMFW -c -o cpe_sql_recover.o cpe_sql_recover.c aarch64-openwrt-linux-gcc -I ../inc -I/home/yzf/host/include/ -g -Wall -DARMFW -c -o cpe_timer.o cpe_timer.c aarch64-openwrt-linux-gcc -I ../inc -I/home/yzf/host/include/ -g -Wall -DARMFW -c -o cpe_xml.o cpe_xml.c cpe_xml.c: In function 'Free_CpeRegisterInfo': cpe_xml.c:102:41: warning: the comparison will always evaluate as 'true' for the address of 'RegInfoTime' will never be NULL [-Waddress] 102 | if(CpeRegisterInfo->RegInfoTime != NULL){ | ^~ In file included from cpe_xml.c:16: ../inc/cpe_xml.h:55:14: note: 'RegInfoTime' declared here 55 | char RegInfoTime[11]; //注册时间 | ^~~~~~~~~~~ aarch64-openwrt-linux-gcc -I ../inc -I/home/yzf/host/include/ -g -Wall -DARMFW -c -o cpe_xml_dump.o cpe_xml_dump.c aarch64-openwrt-linux-gcc cpe_conn.o cpe_epoll.o cpe_fw.o cpe_http.o cpe_main.o cpe_sql.o cpe_sql_recover.o cpe_timer.o cpe_xml.o cpe_xml_dump.o -I ../inc -I/home/yzf/host/include/ -g -Wall -DARMFW -o xml -ldl -L../lib -lxml2 -lcurl -lnet_handle -lsqlite3 -lwhitelist_identifier /home/yzf/toolchain-aarch64_generic_gcc-12.3.0_musl/bin/../lib/gcc/aarch64-openwrt-linux-musl/12.3.0/../../../../aarch64-openwrt-linux-musl/bin/ld: cpe_fw.o:/home/yzf/Nearlink/wgwl/xml_wg/src/../inc/cpe_log.h:16: multiple definition of `ls'; cpe_conn.o:/home/yzf/Nearlink/wgwl/xml_wg/src/../inc/cpe_log.h:16: first defined here /home/yzf/toolchain-aarch64_generic_gcc-12.3.0_musl/bin/../lib/gcc/aarch64-openwrt-linux-musl/12.3.0/../../../../aarch64-openwrt-linux-musl/bin/ld: cpe_http.o:/home/yzf/Nearlink/wgwl/xml_wg/src/../inc/cpe_log.h:16: multiple definition of `ls'; cpe_conn.o:/home/yzf/Nearlink/wgwl/xml_wg/src/../inc/cpe_log.h:16: first defined here /home/yzf/toolchain-aarch64_generic_gcc-12.3.0_musl/bin/../lib/gcc/aarch64-openwrt-linux-musl/12.3.0/../../../../aarch64-openwrt-linux-musl/bin/ld: cpe_main.o:/home/yzf/Nearlink/wgwl/xml_wg/src/../inc/cpe_log.h:16: multiple definition of `ls'; cpe_conn.o:/home/yzf/Nearlink/wgwl/xml_wg/src/../inc/cpe_log.h:16: first defined here /home/yzf/toolchain-aarch64_generic_gcc-12.3.0_musl/bin/../lib/gcc/aarch64-openwrt-linux-musl/12.3.0/../../../../aarch64-openwrt-linux-musl/bin/ld: cpe_sql.o:/home/yzf/Nearlink/wgwl/xml_wg/src/../inc/cpe_log.h:16: multiple definition of `ls'; cpe_conn.o:/home/yzf/Nearlink/wgwl/xml_wg/src/../inc/cpe_log.h:16: first defined here /home/yzf/toolchain-aarch64_generic_gcc-12.3.0_musl/bin/../lib/gcc/aarch64-openwrt-linux-musl/12.3.0/../../../../aarch64-openwrt-linux-musl/bin/ld: cpe_sql_recover.o:/home/yzf/Nearlink/wgwl/xml_wg/src/../inc/cpe_log.h:16: multiple definition of `ls'; cpe_conn.o:/home/yzf/Nearlink/wgwl/xml_wg/src/../inc/cpe_log.h:16: first defined here /home/yzf/toolchain-aarch64_generic_gcc-12.3.0_musl/bin/../lib/gcc/aarch64-openwrt-linux-musl/12.3.0/../../../../aarch64-openwrt-linux-musl/bin/ld: cpe_timer.o:/home/yzf/Nearlink/wgwl/xml_wg/src/../inc/cpe_log.h:16: multiple definition of `ls'; cpe_conn.o:/home/yzf/Nearlink/wgwl/xml_wg/src/../inc/cpe_log.h:16: first defined here /home/yzf/toolchain-aarch64_generic_gcc-12.3.0_musl/bin/../lib/gcc/aarch64-openwrt-linux-musl/12.3.0/../../../../aarch64-openwrt-linux-musl/bin/ld: cpe_xml.o:/home/yzf/Nearlink/wgwl/xml_wg/src/../inc/cpe_log.h:16: multiple definition of `ls'; cpe_conn.o:/home/yzf/Nearlink/wgwl/xml_wg/src/../inc/cpe_log.h:16: first defined here /home/yzf/toolchain-aarch64_generic_gcc-12.3.0_musl/bin/../lib/gcc/aarch64-openwrt-linux-musl/12.3.0/../../../../aarch64-openwrt-linux-musl/bin/ld: cpe_xml_dump.o:/home/yzf/Nearlink/wgwl/xml_wg/src/../inc/cpe_log.h:16: multiple definition of `ls'; cpe_conn.o:/home/yzf/Nearlink/wgwl/xml_wg/src/../inc/cpe_log.h:16: first defined here collect2: error: ld returned 1 exit status make: *** [Makefile:29: xml] Error 1
最新发布
08-13
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值