参考内容:
redis 中以 sds (simple dynamic string,简单动态字符串)来表示字符串(既是 redis 中一种基础数据结构,也是 redis 内部用于代替 c 语言中 char* 的数据结构)。
sds 定义
//定义了一个char 指针
typedef char *sds;
/* Note: sdshdr5 is never used, we just access the flags byte directly.
* However is here to document the layout of type 5 SDS strings. */
struct __attribute__ ((__packed__)) sdshdr5 {
unsigned char flags;
char buf[];
};
//__attribute__ ((__packed__)) 代表structure 采用手动对齐的方式。
struct __attribute__ ((__packed__)) sdshdr8 {
uint8_t len; // 已占用内存单位长度
uint8_t alloc; //buf 分配的长度,等于buf[]的总长度-1,因为buf有包括一个/0的结束符,即总共可用内存单位长度
unsigned char flags; //只有3位有效位,因为类型的表示就是0到4,所有这个8位的flags 有5位没有被用到
char buf[]; // 数据实际的内存空间
};
// 与上面的变化只有 len 和 alloc,使用了 uint16_t, uint32_t, unit64_t
struct __attribute__ ((__packed__)) sdshdr16 {
...
};
struct __attribute__ ((__packed__)) sdshdr32 {
...
};
struct __attribute__ ((__packed__)) sdshdr64 {
...
};

sds 扩容
如果你有稍微看过一点 java 中 ArrayList 的实现的话,两者的实现是类似的。在需要重新分配内存时,如果所需的内存不超过某个限制,那么分配两倍的内存,避免频繁内存分配,如果超过某个限制,那么只分配需要的内存空间。
sds 内存不对齐
内存对齐:简单的说,cpu 读取内存并不是以 byte 为单位的,通常以 64/32 位(也和 cache 的缓存行有关),内存对齐就是将所用的内存填补为读取内存单位的整数倍,下图中的 pad 部分。

内存不对齐的原因我认为并不是一种技术问题,是一种设计的态度,worse is better,能够较简单的实现是最重用的。如果引入内存对齐,那么需要在 32/64 位,以及不同的单位内存长度的 sds 结构做不同的调整,而且为了兼容 char*(sds 使用指针的一些操作兼容了 char* )指针直接指向数据的首位,而不利于获取当前的状态(即移动指针,获取 flag 内容),做内存对齐将会引入这一部分的工作使结构变复杂。