這個問題的前言是,我意識到C宏是一個敏感的話題。很多時候,他們可以通過非宏觀解決方案來實現,這種解決方案更安全,不會遇到經典問題,如增加的參數;所以在那裏,我有一個散列表實現在C與鏈接節點的衝突。我相信大多數人已經看過這一百萬次,但它有點像這樣。這個foreach C宏有多噁心?
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
...
}
我想提供一種通過節點迭代的抽象方式。我認爲使用一個函數,它接受一個函數指針和功能適用於每一個節點,但我經常發現這種解決方案非常有限,所以我想出了這個宏:
#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)
因而可作,如:
tnode_t* n;
tbleach(mytable, n) {
do_stuff_to(n->key, n->value);
}
我能看到的唯一缺點是迭代器索引是表的一部分,所以顯然你不能在同一個表中同時發生兩個循環。我不知道如何解決這個問題,但我不認爲這是一個交易斷路器,考慮這個小宏觀有多大用處。所以我的問題。
** 更新 **
我納入扎克和Jens的建議,刪除與「其他」,並宣佈迭代裏面for語句的問題。一切似乎都奏效,但visual studio抱怨使用宏的地方「不允許使用類型名稱」。我想知道這裏發生了什麼,因爲它編譯和運行,但我不知道迭代器的作用域。
#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
是這種方法不好的形式,如果不是有什麼辦法改進呢?
我忍不住打量着邪惡博士。 「這是一個邪惡的宏?」 – James 2011-02-18 16:02:06
難道你不能將迭代器傳入宏嗎?例如:tbleach(mytable,iterator,n)...這將允許您運行多個循環。 – Nick 2011-02-18 16:03:21