C 语言的字符串函数
C 语言 string 函数,在 C 语言中可以使用 char* 字符数组实现字符串,C 语言标准库 string.h 中也定义了多种字符串操作函数。
字符串使用广泛,需要满足:
- 高效的字符串操作,比如追加、拷贝、比较、获取长度
- 能保存任意的二进制数据,比如图片
- 尽可能省内存
为什么 Redis 不直接使用 C 语言的字符串?
- C 语言 char* 以 ‘\0’标识字符串的结束,则中间含有’\0’的字符串无法被正确表示;也正因为此,没有办法保存图像等二进制数据。
- C 语言 char* 获取字符串长度的时间复杂度是 O(N);追加字符串的时间复杂度也是 O(N),同时可能由于可用空间不足,无法追加。
下面代码展示了 C 语言中 ‘\0’ 结束字符对字符串的影响。下图展示了一个值为 “Redis” 的 C 字符串:
1 | c复制代码#include "stdio.h" |
输出结果是 3 和 5。
SDS 定义
SDS(简单动态字符串) 是 simple dynamic string 的简称,Redis 使用 SDS 作为字符串的数据结构。Redis 中所有的键(key)底层都是 SDS 实现的。
比如:
1 | shell复制代码redis> SET msg "hello world" |
1 | bash复制代码redis> RPUSH fruits "apple" "banana" "cherry" |
Redis sds 源码主要在 sds.h 和 sds.c 中。其中可以发现 Redis 给 char* 起了别名:
1 | c复制代码typedef char *sds; |
SDS 内部结构
SDS 结构中有一个元数据 flags,表示的是 SDS 类型(最低 3 位)。事实上,SDS 一共设计了 5 种类型,分别是 sdshdr5、sdshdr8、sdshdr16、sdshdr32 和 sdshdr64。这 5 种类型的主要区别就在于,它们数据结构中的字符数组现有长度 len 和分配空间长度 alloc,这两个元数据的数据类型不同。
1 | c复制代码/* Note: sdshdr5 is never used, we just access the flags byte directly. |
1 | c复制代码static inline size_t sdslen(const sds s) { |
获取剩余容量:sdsavail 函数,总容量 alloc - 已使用长度 len,时间复杂度是 O(1)。
1 | c复制代码static inline size_t sdsavail(const sds s) { |
SDS 的主要操作 API
基础方法有:
1 | c复制代码sds sdsnewlen(const void *init, size_t initlen); |
字符串初始化
整体和 Java 的 StringBuilder 很像了 O_o
1 | c复制代码/* Create a new sds string starting from a null terminated C string. */ |
首先是判断输入的 init 字符串的长度,接着调用 sdsnewlen 分配内存空间并赋值。
1 | c复制代码sds sdsnewlen(const void *init, size_t initlen) { |
核心函数_sdsnewlen 如下,主要就是先确保空间是否足够、分配空间,然后再调用 memcpy 将 *init 复制到对应的内存空间。
1 | c复制代码/* Create a new sds string with the content specified by the 'init' pointer |
Redis 源码简洁剖析系列
Java 编程思想-最全思维导图-GitHub 下载链接,需要的小伙伴可以自取~
原创不易,希望大家转载时请先联系我,并标注原文链接。
本文转载自: 掘金