Variadic 异构 FREE 宏

Variadic heterogenous FREE macro

我想要一个宏来释放不同类型的多个(可变数字)指针。基于 SO 中的类似问题,我编写了这段似乎有效的代码

#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>

/* your compiler may need to define i outside the loop */
#define FREE(ptr1, ...) do{\
    void *elems[] = {ptr1, __VA_ARGS__};\
    unsigned num = sizeof(elems) / sizeof(elems[0]);\
    for (unsigned i=0; i < num; ++i) free(elems[i]);\
} while(0)


int main(void) 
{
    double *x = malloc(sizeof(double)); /* your compiler may need a cast */
    int    *y = malloc(   sizeof(int)); /* ditto */

    FREE(x, y); 
}

我的问题是

太棒了,是的,使用 void * 是正确的。

您可以稍微改进一下(更多 const,当然可以使用 size_t 而不是 unsigned),但总的来说似乎没问题。

此外,删除 main()there's no need to cast the return value of malloc() in C 中的强制转换,这样做会掩盖实际错误,所以很糟糕。

为了解决 ,您可以通过添加额外的宏扩展步骤将某些内容粘合在一起,该步骤始终在 varargs 宏调用中添加 NULL。这样,您永远不会只用一个参数调用实际的可变参数宏,即使只用一个参数调用顶层宏。当然,调用 free(NULL) 总是安全且定义明确的,所以应该可以。

一个潜在的可用性问题是它不能扩展到只释放一个指针,类似于常规 free。虽然这不是必需的(因为您可以要求用户发现这一点并使用 free),但通常优雅的做法是让事物尽可能通用并自动扩展自身以适应此类用例。

C99 (also C11) 标准第 6.10.3 节第 4 段:

If the identifier-list in the macro definition does not end with an ellipsis ... Otherwise, there shall be more arguments in the invocation than there are parameters in the macro definition (excluding the ...).

即在严格符合 C 中,必须使用 __VA_ARGS__。当使用 -std=c99 -Wall -pedantic:

test.c: In function 'main':
test.c:18:11: warning: ISO C99 requires rest arguments to be used [enabled by default] FREE(x); ^

从技术上讲,您不需要实际值,只需要尾随逗号(FREE(x,); - 空宏参数仍然是一个参数,它填充的数组初始值设定项也允许尾随逗号),但事实并非如此非常...与语言融为一体。

在实践中,真正的编译器不会直接反对缺少 rest-args,但他们可能会对此发出警告(如上所示),因为非致命错误通常可以合理地解释为出现问题的迹象别处。