struct Array{void *ptr; uint64_t cap;}
sizeof(struct Array) //16 struct Array{void *ptr; uint64_t len; uint64_t cap;}
sizeof(struct Array) //24
At any rate, a simple way to get to 16 bytes is the following: struct Array{void *ptr; uint32_t len; uint32_t cap;}
How often does one really need a general array with more than 4B elements?Now thanks to alignment you could use spare bits in the pointer to afford bigger lengths.
struct Array{int64_t ptr:60; uint64_t len:34, cap:34;}2) you could store the capacity before the array payload
But if you meant an actual array as in Rust's [T; N] then it's weird to talk about them as if they've got some specific size, their size is a parameter (N) of the type.
The size of Rust's [u8; 16] or C's unsigned char [16] is 16 bytes but like, duh. And there's no magic here, [u8; 24] or unsigned char [24] is 24 bytes.
This is so I can use regular C pointers to pass them to system functions that expect pointers. Because C still uses just pointers. But I have the length for bounds checking in my own code.
But my resizable types are much bigger. Probably 32 bytes because they store a destructor too. I pass them by pointer because plain pointers are almost always just one item, meaning no bounds checking is necessary.
Yes, that does mean the actual array is two indirections away, but that style gives me a lot of safety because araay indexing is a code smell.
Also in most cases people's destructors don't have associated local state, so, they needn't take up space in each object. All C objects have non-zero size, so if you have an object representing the destructor even if it has no state that takes up space. In C++ there's a hack to avoid paying this price, but in C there is not.
Well, yeah, but I hate all other languages [1], and I'm willing to pay the price in C.
That same sort of thing allowed me to implement RAII in C, though.
[1]: https://gavinhoward.com/2023/02/why-i-use-c-when-i-believe-i...