After reading this chapter, you will be familiar with what a Str looks
like in memory, what the time/space trade-offs are between Str and
char*, and how Str supports features such as automatic memory
management. If you are more interested in using Str than understanding
how it works, (or if you find yourself getting bored) you can safely skip to
chapter 4.
The first design challenge when creating Str was to create a memory
structure that was space efficient but still met the goals of automatic
memory management and efficient operations. Figure 3.1 shows the final
design.
![]() |
Looking at figure 3.1:
data field is a pointer to a buffer that
holds a char* style array. In the empty string case, the length of
the string is set to zero and the data field is set to NULL (0).
data is
pointing to string buffer data on the heap. In the size_and_flags
field, we have the value 0x80000005. This means that the string is 5
bytes long and has the STR_ALLOCATED bit set. When STR_ALLOCATED
is set, Str will automatically free(data) when it is
destructed.
size_and_flags also
has the STR_EXTRA_BUFFER bit set. When this bit is set, a 4-byte field named
buff_size will immediately follow the terminating NULL in the string's
data.
size_and_flags. This allows many string operations
to operate efficiently as they do not have to walk the string to find its
length.
char*
type.
size_and_flags and data bytes.