contributed by < chiehen
>
linux2021
為了有效利用字串儲存空間,自行定義結構 xs 將短字串儲存於 stack 而中長字串儲存於 Heap ,並以將指向此空間的指標儲存於結構中
將定義出此種結構:
union xs | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
char data[16] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
char filter[15] | space_left | flags(4 bits) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
char *ptr | size | capacity | (4 bits) |
其中 capacity 並沒有完全對齊 space_left, 但第二個結構中的 4 bits 有與 flags 對齊
而在此結構中各成員分別代表這意義
這裡可以注意到因為短字串的大小是以剩餘空間定義, 因此當字串長度為 15 時,後面須接著 null terminator '\0'
, 其 ASCII 編碼為 0x00 , 因此在 space_left 及其他 flag 上也仍是正確的值。
因為 C99 6.5.2.3 Structure and union members 中提到的例外規定:
One special guarantee is made in order to simplify the use of unions: if a union contains several structures that share a common initial sequence (see below), and if the union object currently contains one of these structures, it is permitted to inspect the common initial part of any of them anywhere that a declaration of the complete type of the union is visible. Two structures share a common initial sequence if corresponding members have compatible types (and, for bit-fields, the same widths) for a sequence of one or more initial members.
可以發現只要 struct 間的相對成員是 compatible types, 是允許任意查看這些區域的。因此在即使使用 ptr 儲存字串, 仍可查看 is_ptr 等 flag
在主程式中主要對函做了三種操作:
以下將依序解釋:
在實際建立物件時, 檢查使用者欲儲存的是否太大, 如果太大則拒絕, 不然則進入 xs_new 進行字串建立
不太知道 xs_literal_empty()
不知道就說不知,不要裝可愛說「不太知道」,後者對討論無益
jserv
xs_allocate_data
配置 heap 上的記憶體, 反之則將內容複製在至 data (在 stack 上)在配置長字串時預留 4 bytes (int 的大小)作為 reference counter
在建立長字串也將 reference counter 設為 1
需要討論 reference counting 的設計考量
jserv
「與其他 string 共用記憶體」此描述可能會誤導讀者,應聲明為,指向同一份記憶體空間,「共用」(share) 隱含的意思和該函式實際行為不同。
jserv
'\n'
(0x0A), 而欲比較對象為 'A'
(0x41) 舉例說明:
set_bit('\n')
將 mask[1] 的第 3 個位元(LSB 為第 1 個位元) 設成 1check_bit('A')
將比對 mask[8] 的第 2 個位元 (即 'A' 在 mask 上的編碼) 是否為 1路見不平,拿 patch 來填!
jserv
參考 C++ 再探 string 之 eager-copy, COW 和 SSO 方案
對不同長度的字串做不同程度的拷貝: 長字串做 CoW, 其他做深度拷貝
將 LARGE_STRING_LEN
改為 30
進行測試
可以發現因為對長字串使用 copy on write, 所以 data 地址相同