我想要一个宏来释放不同类型的多个(可变数字)指针。 基于SO中的类似问题,我制作了这个代码似乎有效
#include #include #include /* 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); }
我的问题是
一个潜在的可用性问题是它不能扩展到只释放一个指针,类似于常规的free
。 虽然这不是必需的(因为您可能要求用户发现并free
使用),但通常优雅的是尽可能通用并自动扩展以适应此类用例。
C99 (也是C11 )标准第6.10.3段第4段:
如果宏定义中的标识符列表没有以省略号结尾…否则,调用中的参数应该多于宏定义中的参数(不包括
...
)。
即在严格符合C的情况下,必须使用__VA_ARGS__
。 当使用-std=c99 -Wall -pedantic
时,GCC甚至会为你强调这一点(编译器无法certificate某些东西是合规的,但它可以警告你什么时候没有):
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,但是他们可能会警告它(如上所示),因为非致命错误通常是合理的,可以解释为其他地方出现问题的迹象。
这很酷,是的,使用void *
是正确的。
你可以稍微改进它(更常见,当然使用size_t
而不是unsigned
)但总的来说它似乎没问题。
另外,在main()
删除强制转换, 不需要在C中强制转换malloc()
的返回值,这样做可以掩盖实际错误,所以它很糟糕。
为了解决@ Leushenko的答案 ,您可以通过添加额外的宏扩展步骤来粘合一些东西,该步骤总是在varargs宏调用中添加NULL。 这样,即使只用一个参数调用顶层宏,你也永远不会用一个参数调用实际的varargs宏。 当然,调用free(NULL)
总是安全且定义良好的,所以应该可行。
以上就是c/c++开发分享Variadic异质FREE宏相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/c-cdevelopment/549675.html