printf("%zu %d\n", list_len(l), *l[0]); // Prints 1 1.
This prints raptors unless your list is of size_t.
#define list_lenref(l) ((size_t*)l)[-1]
The only way to write this kind of size-prefixed plain array in legal C will involve separate getter/setters to explicitly copy the size in and out. It's not as simple as getting a reference because you cannot recast an arbitrary array as a pointer to size_t and read/write to it. A compiler might be happy to optimize these accesses out altogether.
Note the ((char* )l). Pointer arithmetic on void* as used elsewhere in the code is a GNU extension. This is easily fixed by instead casting to char* or u/intptr_t.
Otherwise this style of list is just fine, in fact it's not necessarily limited to pointer types.
4. Doesn't properly () macro argument and lots of macros also reuse their arguments. That sure is going to be fun to debug, e.g. list_len(l++);
In short, if this works for the author - great, but the re-usability of this code is next to zero. The beauty of C is that it's very explicit and verbose. Once you start concealing things behind abstract APIs, you start trading verbosity for implicit invariants leading to obscure bugs and intense head scratching. Not a worthy trade off in hell of a lot of cases.
As the article states, this only supports lists of pointer types. The result would be the same bad performance that Bjarne Stroustrup warns of in the cited talk on linked lists. Each of these pointers will be random memory positions giving you bad cache hits.
list_append needn't take a second argument that is assigned across. If you've got an array of structs, you can then initialise the struct members in place.
I was a bit unsure about it at first, but having used it for a few months I've ended up quite happy with it:
- Easy to examine in a debugger;
- Code is fairly straightforward (taking into account the usual macro token pasting nonsense);
- Less risk of falling foul of whatever UB nonsense the gcc/clang people have decided to pull this week;
- Simple interop with foreign APIs (of course, reading is very easy; and my implementation explicitly allows the capacity to be smaller than the size in order to allow creation of one)
Not very convenient to pass these things to a function, though. I also don't like that the ARRAY macro generates 3 declarations. These don't really seem to be problems in practice however.
This might not be to all tastes, but there you go.
[+] [-] 0x09|10 years ago|reply
Otherwise this style of list is just fine, in fact it's not necessarily limited to pointer types.
[+] [-] opk|10 years ago|reply
[+] [-] abcd_f|10 years ago|reply
2. my_list_type.my_array is not properly aligned
3. list_append() doesn't handle realloc() failures
4. Doesn't properly () macro argument and lots of macros also reuse their arguments. That sure is going to be fun to debug, e.g. list_len(l++);
In short, if this works for the author - great, but the re-usability of this code is next to zero. The beauty of C is that it's very explicit and verbose. Once you start concealing things behind abstract APIs, you start trading verbosity for implicit invariants leading to obscure bugs and intense head scratching. Not a worthy trade off in hell of a lot of cases.
[+] [-] opk|10 years ago|reply
list_append needn't take a second argument that is assigned across. If you've got an array of structs, you can then initialise the struct members in place.
[+] [-] to3m|10 years ago|reply
I was a bit unsure about it at first, but having used it for a few months I've ended up quite happy with it:
- Easy to examine in a debugger;
- Code is fairly straightforward (taking into account the usual macro token pasting nonsense);
- Less risk of falling foul of whatever UB nonsense the gcc/clang people have decided to pull this week;
- Simple interop with foreign APIs (of course, reading is very easy; and my implementation explicitly allows the capacity to be smaller than the size in order to allow creation of one)
Not very convenient to pass these things to a function, though. I also don't like that the ARRAY macro generates 3 declarations. These don't really seem to be problems in practice however.
This might not be to all tastes, but there you go.
(Here's another option, that's more like the link here: https://github.com/nothings/stb/blob/master/stretchy_buffer.... - note note about strict aliasing, which I imagine could apply to the list macros here as well. Obligatory links: http://blog.metaobject.com/2014/04/cc-osmartass.html, http://robertoconcerto.blogspot.co.uk/2010/10/strict-aliasin...)
[+] [-] audidude|10 years ago|reply
[+] [-] jevgeni|10 years ago|reply
[+] [-] nrj|10 years ago|reply
[+] [-] Ace17|10 years ago|reply