您的位置:

memchr函数详解

一、memchr函数

memchr(memory char)是一个标准库函数,用于查找内存块中的一个字节,其函数定义如下:

void *memchr(const void *s, int c, size_t n);

其中,s是需要查找的内存块指针,c是需要查找的字符,n是需要查找的内存块大小。

二、memchr函数的用法

memchr函数可以用于查找一个字符在字符串中的位置。下面是一个示例代码:

char str[] = "hello world";
char *ptr = (char*)memchr(str, 'o', strlen(str));
if (ptr != NULL) {
    printf("第一个o的位置是:%ld\n", ptr - str + 1);
}

输出结果:

第一个o的位置是:5

代码解释:首先将一个字符串赋值给字符串数组str,然后将字符'o'作为第二个参数传递给memchr函数,第三个参数是字符串数组str的长度。如果找到了字符'o'的位置,则指针ptr指向该位置,否则指针ptr指向NULL。最后输出字符'o'在字符串中的位置。

三、memchr函数的性能

memchr函数是一种非常高效的查找字符在字符串中的位置的方法,因为它是直接在内存中查找,而不是通过字符串的遍历进行查找。

下面是一个基准测试代码,用于比较memchr函数和字符串遍历法的性能:

#include <stdio.h>
#include <time.h>
#include <string.h>

#define REPEAT 1000000

long current_timestamp() {
    struct timeval te; 
    gettimeofday(&te, NULL); 
    long milliseconds = te.tv_sec*1000000LL + te.tv_usec; 
    return milliseconds;
}

int main() {
    char str[] = "abcdefghijklmnopqrstuvwxyz";
    char *ptr = NULL;
    long start, end;

    // test memchr
    start = current_timestamp();
    for (int i = 0; i < REPEAT; i++) {
        ptr = (char*)memchr(str, 'z', strlen(str));
    }
    end = current_timestamp();
    printf("memchr: %ld us\n", end - start);

    // test travese string
    start = current_timestamp();
    for (int i = 0; i < REPEAT; i++) {
        for (int j = 0; j < strlen(str); j++) {
            if (str[j] == 'z') {
                ptr = &str[j];
                break;
            }
        }
    }
    end = current_timestamp();
    printf("travese string: %ld us\n", end - start);

    return 0;
}

输出结果:

memchr: 33 us
travese string: 1080 us

代码解释:这个测试用例分别测试了memchr函数和字符串遍历法的性能,先构造一个包含26个字符的字符串,然后从中查找字母'z'的位置计时1000000次。可以发现,memchr函数的查找速度非常快,而字符串遍历法的速度相对就比较慢。

四、memchr头文件

memchr函数定义在头文件string.h或strings.h中,因此,需要使用memchr函数时,需要在代码文件中包含这个头文件。

#include <string.h>

五、memchr API

下面是memchr函数的详细API文档:

函数定义:
void *memchr(const void *s, int c, size_t n);
参数说明:

s - 这是指向源字符串的指针。

c - 这是要查找的字符。

n - 这是要查找的前n个字符的长度,也就是源字符串的长度。

返回值:

该函数返回在内存块s中查找到的字符c的指针,如果未找到字符c,则返回NULL。

六、memchr汇编实现

下面是memchr函数的汇编实现代码:

 1   memchr:
 2     mov rax, rdi                      ; rax = s
 3     mov ecx, edi                      ; ecx = c
 4     mov edx, esi                      ; edx = n
 5     sub esi, 1                        ; n--
 6     cmp esi, -1                       ; if (n < 0)
 7     jb .exit                          ;     return NULL
 8   .loop:
 9     cmp byte [rax], cl                ; if (*s == c)
10     je .found
11     add rax, 1                        ; s++
12     dec esi                           ; n--
13     jnz .loop                         ; else continue
14   .exit:
15     xor eax, eax                      ; return NULL
16     ret
17   .found:
18     ret                              ; return s

代码解释:这个汇编实现会比C代码实现快得多,因为它直接使用了x86_64汇编指令。

七、memchr类似函数选取

除了memchr函数,还有其它类似的函数可以被用来查找内存块中的一个字符。例如:

  • strchr: 从字符串中查找一个字符
  • strstr: 在字符串中查找一个子字符串

下面是strchr函数的例子:

char * str = "hello world";
char *pch = strchr(str, 'l');
while (pch != NULL) {
    printf("l found at %ld\n", pch - str + 1);
    pch = strchr(pch + 1, 'l');
}

输出结果:

l found at 3
l found at 4
l found at 10

代码解释:首先将一个字符串赋值为char*类型的指针str,然后调用strchr函数查找字符串中第一个字符‘l’的位置,然后每次循环都通过指针的偏移量再次查找。 strch() 和 memchr() 在用途上相似,但 strchr() 只能查找字符,而 memchr() 能在字节序列中查找任意值。