通用C宏,用于简单的链接列表附加



我们的C代码库乱扔了类似图案的代码,这些代码在具有相同类型的.next指针的结构上执行相同的迭代,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: warning: statement with no effect [-Wunused-value] (what); ^ cachedb/cachedb.c:797:9: note: in expansion of macro ‘add_last’ return add_last(new, existing); ^ cachedb/../db/../ut.h:110:4: warning: statement with no effect [-Wunused-value] (where); ^ cachedb/cachedb.c:797:9: note: in expansion of macro ‘add_last’ return add_last(new, existing); ^ cachedb/../db/../ut.h:103:2: error: void value not ignored as it ought to be ({ if (!(where)) { ^ cachedb/cachedb.c:797:9: note: in expansion of macro ‘add_last’ return add_last(new, existing); ^

我已经尝试使用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);

和原始return代码变为:

add_last(filter, filters);
return filters;

仍然,任何暗示原始解决方案为何引发这些警告都会有所帮助。这些不是"没有效果的语句"恕我直言 - 它们可用作块返回值。

最终答案:为了使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:(

最新更新