Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/61.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
用于简单链表追加的通用C宏_C_Macros - Fatal编程技术网

用于简单链表追加的通用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) {

我们的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) {
        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块返回它们最后一个语句的值——在我们的例子中(第一个宏),这是一件有用的事情!你看,这正是我想要做的