4 ms·
typedef struct {uint8_t *data; size_t len;} ByteBuf; is the first line of code I write in a C project.
by ATsch 7y ago
typedef struct {uint8_t *data; size_t len;} ByteBuf; is the first line of code I write in a C project.
- enriquto 7y agoThat's a really bizarre layout for your struct. Why don't you put the length first?
- ATsch 7y agoI'm not sure if it matters. It might be better for some technical reason, such as speeding up double dereferences, because you don't need to add anything to get to the pointer. But to be honest I just copied it out of existing code.
- saagarjha 7y agoMost platforms have instructions for dereferencing with a displacement.
- twic 7y agoWhy would it matter? The bytes aren't inline, this is just a struct with two word-sized fields. A possible tiny advantage for this layout is that a pointer to this struct can be used as a pointer to a pointer-to-bytes, without having to adjust it. Although i'm not sure that's not undefined behaviour.
- epr 6y agoI don't think that's undefined behavior. That's how C's limited form of polymorphism is utilized. For example, many data structures behind dynamic languages are implemented in this way. A concrete example would be Python's PyObject which share PyObject_HEAD. https://github.com/python/cpython/blob/master/Include/object.h https://github.com/python/cpython/blob/master/Include/object...
- kkdwivedi 7y agoAnother option is a struct with a FAM at the end. typedef struct { size_t len; uint8_t data[]; } ByteBuf; Then, allocation becomes ByteBuf *b = malloc(sizeof(*b) + sizeof(uint8_t) * array_size); b->len = array_size; and data is no longer a pointer.
- ATsch 7y agoWell, your ByteBuf is still a pointer. You also now need to dereference it to get the length. It also can't be passed by value, since it's very big. You can also not have multiple ByteBufs pointing at subsections of the same region of memory. Thing is, you rarely want to share just a buffer anyway. You probably have additional state, locks, etc. So what I do is embed my ByteBuf directly into another structure, which then owns it completely: typedef struct { ... ByteBuf mybuffer; ... } SomeThing; So we end up with the same amount of pointers (1), but with some unique advantages.
- kevin_thibedeau 7y agoThis will an alignment problem on any platform with data types larger than size_t. You'd need an alignas(max_align_t) on the struct. At which point some people are going to be unhappy about the wasteful padding on a memory constrained target.
- mobilemidget 6y agoCould you add some extra information why this is so helpful or handy to have? Think it will benefit readers that are starting out with C etc.
- saagarjha 6y agoIn C, dynamically-sized vectors don’t carry around size information with them, often leading to bugs. This struct attempts to keep the two together.
- GoblinSlayer 6y agoMemory corruption in sudo password feedback code happened because length and pointer sit as unrelated variables and have to be manipulated by two separate statements every time like some kind of manually inlined function. For comparison putty slice API handles slice as a whole object in a single statement keeping length and pointer consistent.
- benibela 6y agoWhy not typedef struct {uint8_t *data, dataend} ? Makes it easier to take subranges out of it
- orenht 6y agoshould be typedef struct {uint8_t *data, *dataend} if I'm not mistaken :)
- gkfasdfasdf 6y agoWhat are the advantages of saving the end as a pointer? Genuinely curious. Seems like a length allows the end pointer to be quickly calculated (data + len), while being more useful for comparisons, etc.
- benibela 6y agoYou can remove the first k elements of a view with data += k. With the length you would need to do data += k; length -= k Especially if you want to use it as safe iterator, you can do data++ in a loop
- gkfasdfasdf 6y agoGot it. That is really neat, going to add to my bag of tricks...
- zoomablemind 6y ago> ...You can remove the first k elements of a view with data += k. How would you safely free(data) afterwards? You'd need to keep an alloc'ed pointer somehow.
- benibela 6y agoRight. I always think the pointer declaration is part of the type. (that is why I do not use C. Is there really a good reason for this C syntax?)