用于简单链表追加的通用C宏
我们的C代码库中充斥着类似模式的代码,这些代码执行相同的迭代、用于简单链表追加的通用C宏,c,macros,C,Macros,我们的C代码库中充斥着类似模式的代码,这些代码执行相同的迭代、NULL处理等。对于具有的结构上的任何“列表附加”操作。下一步指针的类型与自身相同: struct foo { int bar; char *baz; struct foo *next; } 模式代码示例: struct foo *foo_list; int func(struct foo *f) { struct foo *it; ... if (!foo_list) {
NULL
处理等。对于具有的结构上的任何“列表附加”操作。下一步
指针的类型与自身相同:
struct foo {
int bar;
char *baz;
struct foo *next;
}
模式代码示例:
struct foo *foo_list;
int func(struct foo *f) {
struct foo *it;
...
if (!foo_list) {
foo_list = f;
} else {
for (it = foo_list; it->next; it = it->next)
{}
it->next = f;
}
...
}
我正试图想出一个宏,它可以简化任何具有这样一个.next
成员的结构的追加过程。请记住,也可以对NULL
列表进行添加,因此宏还必须返回新的列表头:
#define add_last(what, where) \
({ \
if (!(where)) { \
(what); \
} else { \
typeof(where) __wit = (where); \
while (__wit->next) \
__wit = __wit->next; \
__wit->next = (what); \
(where); \
}})
但是,这样使用时:
return add_last(filter, filters);
,gcc
不太高兴,吐出:
cachedb/./db/./ut.h:104:4:警告:声明无效[-Wunused值]
(什么)\
^
cachedb/cachedb.c:797:9:注意:在宏“add_last”的扩展中
返回上一次添加(新的、现有的);
^
cachedb/./db/./ut.h:110:4:警告:声明无效[-Wunused值]
(在何处)\
^
cachedb/cachedb.c:797:9:注意:在宏“add_last”的扩展中
返回上一次添加(新的、现有的);
^
cachedb/./db/./ut.h:103:2:错误:未按应忽略的方式忽略void值
({if(!(where)){\
^
cachedb/cachedb.c:797:9:注意:在宏“add_last”的扩展中
返回上一次添加(新的、现有的);
^
我尝试了
do while(0)
块,也没有运气。我尝试的是可能的吗?谢谢!我稍微改变了宏的内部行为。它不仅现在可以工作,而且更适合代码库:
#define add_last(what, where) \
do { \
if (!(where)) { \
(where) = (what); \
} else { \
typeof(where) __wit = (where); \
while (__wit->next) \
__wit = __wit->next; \
__wit->next = (what); \
} \
} while (0)
因此,不要像下面那样使用它,它在大多数情况下都会执行无关的写入操作:
filters = add_last(filter, filters);
,您现在只需像这样使用它:
add_last(filter, filters);
原始的返回
代码变为:
add_last(filter, filters);
return filters;
不过,任何关于原始解决方案为何抛出这些警告的提示都会有所帮助。这些不是“无效语句”IMHO-它们作为块返回值很有用
最终答案:为了让C块返回一个值,值必须只放在一个简单的、以冒号结尾的表达式()中,否则该块将返回void
。因此,我们最初的宏思想(无论如何我将不再使用)只有在如下调整时才能起作用:
#define add_last(what, where) \
do { \
typeof(where) __wit; \
if (!(where)) { \
__wit = (what); \
} else { \
__wit = (where); \
while (__wit->next) \
__wit = __wit->next; \
__wit->next = (what); \
__wit = (where); \
} \
__wit; \
} while (0)
这最终会使
gcc
高兴:)我稍微改变了宏的内部行为。它不仅现在可以工作,而且更适合代码库:
#define add_last(what, where) \
do { \
if (!(where)) { \
(where) = (what); \
} else { \
typeof(where) __wit = (where); \
while (__wit->next) \
__wit = __wit->next; \
__wit->next = (what); \
} \
} while (0)
因此,不要像下面那样使用它,它在大多数情况下都会执行无关的写入操作:
filters = add_last(filter, filters);
,您现在只需像这样使用它:
add_last(filter, filters);
原始的返回
代码变为:
add_last(filter, filters);
return filters;
不过,任何关于原始解决方案为何抛出这些警告的提示都会有所帮助。这些不是“无效语句”IMHO-它们作为块返回值很有用
最终答案:为了让C块返回一个值,值必须只放在一个简单的、以冒号结尾的表达式()中,否则该块将返回void
。因此,我们最初的宏思想(无论如何我将不再使用)只有在如下调整时才能起作用:
#define add_last(what, where) \
do { \
typeof(where) __wit; \
if (!(where)) { \
__wit = (what); \
} else { \
__wit = (where); \
while (__wit->next) \
__wit = __wit->next; \
__wit->next = (what); \
__wit = (where); \
} \
__wit; \
} while (0)
这将最终使
gcc
happy:)你能展示一个吗。这是一个很好的起点;我稍微改变了我自己对MCV的看法,并使其发挥作用-也将更新问题我希望我永远不必调试此代码:(@harper当然inline
rocks,但是如何解决键入问题?next
肯定会在不同的结构中放置在不同的偏移位置。你能展示一个吗。这是一个很好的起点;我稍微改变了我自己对MCV的看法,并使它工作了-也会更新问题我希望我永远不用调试它s代码:(@harper当然inline
rocks,但是如何解决键入问题?next
肯定会在不同的结构中放置在不同的偏移位置。有关提示,请显示a。它们到底有多大用处?if(!(过滤器))(过滤器)
当然过滤器
是一个表达式,所以它是一个有效的语句,但它没有任何效果,它只是一个变量名。但是返回
不是在使用它吗?这是我不明白的部分。我有一个印象,C块返回它们最后一个语句的值——在我们的例子中(第一个宏),这是很有用的!请看-正是我想做的。提示请显示一个。它们到底有多有用?if(!(过滤器))(过滤器)
当然过滤器
是一个表达式,所以它是一个有效的语句,但它没有任何效果,它只是一个变量名。但是返回
不是在使用它吗?这是我不明白的部分。我有一个印象,C块返回它们最后一个语句的值——在我们的例子中(第一个宏),这是一件有用的事情!你看,这正是我想要做的