数据结构之动态字符串

//类型别名,用于指向 sdshdr 的 buf 属性
typedef char *sds;

//保存字符串对象的结构
struct sdshdr {
    
    // buf 中已占用空间的长度
    int len;

    // buf 中剩余可用空间的长度
    int free;

    // 数据空间
    char buf[];
};

        动态字符串是redis的基础数据结构之一,这里并没有简单地只用C中常用的char *类型来保存字符串,而是创建了一个sdshdr的结构体,该结构体包含三个组成元素,字段len保存字符串的实际长度,free记录申请的剩余空间,buf[]保存真正的字符串内容。

        因为这样一个结构体的存在,当要获取字符串的长度时,就不必像传统的C语言那样遍历字符串然后通过计数最后得到组付出长度,这里直接通过len字段就可以获取,时间复杂度由o(n)变为o(1)。

另外,根据给定的字符串初始化该结构体时,最终调用的是sdsnewlen(const void *init, size_t initlen)方法。如下:

sds sdsnewlen(const void *init, size_t initlen) {

    struct sdshdr *sh;

    // 根据是否有初始化内容,选择适当的内存分配方式
    if (init) {
        // zmalloc 不初始化所分配的内存
        sh = zmalloc(sizeof(struct sdshdr)+initlen+1);
    } else {
        // zcalloc 将分配的内存全部初始化为 0
        sh = zcalloc(sizeof(struct sdshdr)+initlen+1);
    }

    // 内存分配失败,返回
    if (sh == NULL) return NULL;

    // 设置初始化长度
    sh->len = initlen;
    // 新 sds 不预留任何空间
    sh->free = 0;
    // 如果有指定初始化内容,将它们复制到 sdshdr 的 buf 中
    if (initlen && init)
        memcpy(sh->buf, init, initlen);
    // 以 \0 结尾
    sh->buf[initlen] = '\0';

    // 返回 buf 部分,而不是整个 sdshdr
    return (char*)sh->buf;
}

        该方法有两个形参,第一个形参*init保存的是字符串本身,第二个initlen记录的是该字符串长度。初始化结构体首先是在内存中动态申请一段存储空间,长度是sizeof(struct sdshdr)+initlen+1,第一部分是结构体本身的长度,中间部分是该字符串本身的长度,最后的1存储的是空字符'\0',以作为字符串的结尾。若分配失败则返回NULL,反之则给结构体中各字段赋值。注意,该方法最终返回的是字符串本身部分,也就是sds类型,而不是整个sdshdr。

        然而实际情况一般都是只有一个参数,也就是字符串本身,这时就先需要通过方法strlen()求出字符串长度,然后再调用上述方法初始化。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值