C 可变异质自由宏

C 可变异质自由宏,c,macros,C,Macros,我想要一个宏来释放多个不同类型的可变数字指针。基于类似的问题,所以我做了这个代码,这似乎是可行的 #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

我想要一个宏来释放多个不同类型的可变数字指针。基于类似的问题,所以我做了这个代码,这似乎是可行的

#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*数组是否正确?我在*int[]中看到了相同的技巧,所以问题是*void[]会做我所期望的吗 代码C99兼容吗?是否有编译器会遇到此问题?
这很酷,是的,使用void*是正确的

您可以将其改进得更为恒定,当然可以使用size\u t而不是unsigned,但总体来说似乎还可以

此外,在main中删除强制类型转换,这样做可以掩盖实际错误,因此它只是不好的


为了解决这个问题,您可以通过添加一个额外的宏扩展步骤将某些内容粘合在一起,该步骤总是在varargs宏调用中添加一个NULL。这样,即使只使用一个参数调用顶级宏,也永远不会只使用一个参数调用实际的varargs宏。当然,调用freeNULL总是安全且定义良好的,所以这应该是可行的。

一个潜在的可用性问题是,它不能扩展到仅释放一个指针,类似于常规的free。虽然这是不必要的,因为您可以要求用户发现这一点并免费使用,但通常情况下,尽可能通用并自动扩展自己以适应此类用例是很优雅的

标准第6.10.3节第4段:

如果宏定义中的标识符列表没有以省略号结尾。。。否则,调用中的参数应多于宏定义中的参数,不包括

i、 e.在严格符合C的情况下,必须使用_VA_ARGS。GCC甚至会为您强调这一点,因为编译器无法证明某些内容是符合的,但在使用-std=c99-Wall-pedantic时,它会在不符合时向您发出警告:

测试c:在函数“main”中: test.c:18:11:警告:ISO C99要求使用rest参数[默认启用] 弗里克斯; ^

从技术上讲,您不需要实际值,只需要后面的逗号FREEx;-一个空的宏参数仍然是一个参数,它填充的数组初始值设定项也允许尾随逗号,但这不是很。。。与语言相结合


实际上,真正的编译器不会直接反对缺少rest参数,但他们可能会如上所示发出警告,因为非致命错误通常可以合理地解释为其他地方出了问题。

如果您的目标是C99,为什么要在循环外声明i?!你为什么要投malloc的结果?@KerrekSB我写C时有点紧张;过去版本的鬼魂让我这么做:P。。。将编辑问题,请注意:1。您可以在宏中删除ptr1。2.声明i为无符号,类似于num.3。函数main应该返回一个值。4.您还应该包括stdlib.h.@barakmanos 1。不要冒险创建0大小的数组,并且由于宏扩展而产生无法理解的错误消息,最好使用强制参数2。同意3。隐性收益types@barakmanos在Leushenko给出答案之后,我不得不承认,对于警告案来说,权衡并不能完全解决问题。Thnx最初指出ptr1问题实际错误OP通过不包括stdlib.h而实际犯下的错误:-看起来VS以其自身的风格实现了C99,我需要使用初始代码,但我更新了问题以符合更正和C99,thnxOk,所以我们又失去了ptr1?嗯,这是一个论点,它可能会引起警告,这是一些人不喜欢的。如果您仍然认为与更好的潜在错误消息进行权衡是值得的,那么就保留它。@Nope compliance beats warnings也将归功于barak manos。Thnx为了彻底起见,我将不修改这个问题,以便这个答案与上下文保持一致