How evil is this foreach C macro? -


the preface question that, realize c macros touchy subject. many time can accomplished non-macro solution more secure , not subject classic problems incremented arguments; out of way, have hash table implementation in c linked nodes collision. i'm sure have seen million times goes bit this.

typedef struct tnode_t {     char* key; void* value; struct tnode_t* next; } tnode_t;  typedef struct table_t {     tnode_t** nodes;     unsigned long node_count;     unsigned long iterator; // see macro below         ... } 

i provide abstracted way of iterating through nodes. considered using function takes function pointer , applies function each node find kind of solution limiting came macro:

#define tbleach(table, node) \     for(node=table->nodes[table->iterator=0];\         table->iterator<table->node_count;\         node=node?node->next:table->nodes[++table->iterator])\             if (node) 

which can used like:

tnode_t* n; tbleach(mytable, n) {     do_stuff_to(n->key, n->value); } 

the downside can see iterator index part of table not have 2 loops going on @ same time in same table. not sure how resolve don't see deal breaker considering how useful little macro be. question.

** updated **

i incorporated zack , jens's suggestion, removing problem "else" , declaring iterator inside statement. appears work visual studio complains "type name not allowed" macro used. wondering happens here because compiles , runs not sure iterator scoped.

#define tbleach(table, node) \     for(node=table->nodes[0], unsigned long i=0;\         i<table->node_count;\         node=node?node->next:table->nodes[++i])\         if (!node) {} else 

is approach bad form , if not there way improve it?

the unacceptable thing in there said -- iterator part of table. should pull out so:

typedef unsigned long table_iterator_t; #define tbleach(table, iter, node) \     ((iter) = 0, (node) = (table)->nodes[(iter)]; \          (iter) < (table)->node_count; \          (node) = ((node) && (node)->next) \                   ? (node)->next : (table)->nodes[++(iter)])  // use: table_iterator_t i; tnode_t *n; tbleach(mytable, i, n) {     do_stuff_to(n->key, n->value); } 

i sucked if statement for-loop expresssions because it's safer way (weird things not happen if next token after close brace of loop body else). note array entry table->nodes[table->node_count] will read from, unlike usual convention, need allocate space (and make sure it's null). true version well, think.

edit: corrected logic case table entry null.


Comments

Popular posts from this blog

apache - Add omitted ? to URLs -

redirect - bbPress Forum - rewrite to wwww.mysite prohibits login -

php - How can I stop spam on my custom forum/blog? -