3 ms·
My growable array "system" is more along these lines: #define CONCAT(A,B) A##B #define ALEN_NAME(N) CONCAT(N,_length) #define ACAP_NAME(N) CONCAT(N
by to3m 11y ago
My growable array "system" is more along these lines:
#define CONCAT(A,B) A##B
#define ALEN_NAME(N) CONCAT(N,_length)
#define ACAP_NAME(N) CONCAT(N,_capacity)
#define ARRAY(T,N) \
T *N; \
size_t ALEN_NAME(N); \
size_t ACAP_NAME(N)
#define AINIT(N) do {N=NULL;ALEN(N)=0;ACAP(N)=0;}while(0)
#define ADESTROY(N) do{free(N);AINIT(N);}while(0)
#define ALEN(N) (ALEN_NAME(N))
#define ACAP(N) (ACAP_NAME(N))
#define AADD(N,V) \
do { \
if(ALEN(N)>=ACAP(N)) {N=Grow(&ACAP(N),(N),ALEN(N),sizeof *N,1);} \
N[ALEN(N)++]=V; \
} while(0)
(etc., etc.)
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.h 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://blog.metaobject.com/2014/04/cc-osmartass.html, http://robertoconcerto.blogspot.co.uk/2010/10/strict-aliasing.html http://robertoconcerto.blogspot.co.uk/2010/10/strict-aliasin...)