macros - 在 C 中,您可以将具有多个值的宏传递给函数吗
问题描述
我有一个消息传递函数,它接受可变数量的参数,因为它以与 printf 相同的方式支持字符串格式化。然后我的计划是用一个单一的定义消息代码和消息,#define
并能够通过传递一个与紧密相关的东西的单个参数来调用这个函数。
这是消息宏:
#define MSG(a, b, ...) message(__FILE__, __LINE__, a, b, __VA_ARGS__);
这是消息代码和字符串定义的示例:
#define MSG_INIT 0000,"%s INITIALIZED SUCCESSFULLY"
当我尝试以以下形式拨打电话时,会出现此问题:
MSG(MSG_INIT);
我的 IDE 给了我一个错误,如下所示:
'Expands to message("file.c", 1, 0000, "INITIALIZED SUCCESSFULLY",);
最后一个','导致问题的地方。
我期待看到:
'Expands to message("file.c", 1, 0000, "INITIALIZED SUCCESSFULLY");
如果我将呼叫更改为:
MSG(MSG_INIT,NULL);
一切都很好,但我宁愿不传递 NULL,因为MSG_INIT
首先定义的目的是传递更少的参数。有些消息使用了__VA_ARGS__
(例如:#define MSG_CONNECT 0001,"CONNECTION TO [%s] ESTABLISHED"
使用匹配的 call MSG(MSG_CONEST, server_ip);
),因此摆脱它不是一种选择。我只是在寻找解决此问题的最佳方法,并且我知道很多人建议远离预处理器,但这是我想到的最佳解决方案。
解决方案
我知道很多人建议远离预处理器......
我不知道这是为什么。可能是出于同样的原因你不得不问这个问题吗?:-)
老实说,预处理器应该仅限于包含头文件和进行条件编译。它曾经用于的任何其他东西,例如:
#define RC_OK 0
#define RC_NOMEM 1
#define HALF_OF(x) x / 2
使用枚举或函数做得更好。
类似函数的宏的时代应该被抛在脑后,特别是因为现代编译器可以很容易地优化大多数手工编写的代码,并且不会HALF_OF
像上面的那个宏那样出现细微的错误(不要使用它,我专门做了说明一点是错误的)。
它实际上只是一个文本替换的东西,它理解词汇元素,但不是 C 的完整语法。事实上,你必须执行我所说的“宏观体操”才能让它做除了简单的事情之外的任何事情,这就是足够的理由避开。为此使用功能,它会让你的生活更轻松。
并且很抱歉没有解决您的具体问题,我只是认为使用预处理器的任何解决方案充其量都是半生不熟的。但是在回答“IX 怎么做?”这个问题时,有很多关于 SO 的先例。用“不要X,最好是Y。” 想想用汇编程序编写会计包,用面向对象的 COBOL 编写操作系统,或者用 Pascal 编写任何东西:-)
但是,如果您真的想按照我的建议坚持使用宏,您可以尝试从以下内容开始:
#include <stdio.h>
#define MSG(fmtStr, ...) printf("%s:%d> " fmtStr, __FILE__, __LINE__, __VA_ARGS__)
#define MSG_INIT "Initialised %s\n"
#define MSG_TERM "Terminated %s with values %d and %d\n"
int main(void) {
MSG("%f\n", 42.3);
MSG(MSG_INIT, "something");
MSG(MSG_TERM, "something else", 7, 42);
}
我认为这是可移植的,它允许您将繁重的工作放入MSG
并为其余内容使用单独的格式字符串和参数:
testprog.c:8> 42.300000
testprog.c:9> Initialised something
testprog.c:10> Terminated something else with values 7 and 42
推荐阅读
- python - 如何根据 pip freeze 的输出修改安装模块版本
- java - 为什么我的“套装结果”显示第一次测试数据两次?
- java - 捆绑的 Java-Application 被识别为 32 位,它会在 macOS 10.15 Catalina 下运行吗?
- puppeteer - Puppeteer - 点击在 slowMo 之外不起作用
- c# - 始终在桌面上开发 Windows 10 小部件应用程序
- python - 如何在 virtualenv 中安装 python 源代码?
- powershell - 有没有办法设置一个变量以将输出放置到标准输出或空值?
- laravel - 如何在我的开发环境中使用 laravel 发送电子邮件,用户会收到什么?
- flask - 有没有办法在使用 Flask-appbuilder 内置表单时对用户输入数据添加自定义验证?
- javascript - JavaScript 中的字符串替换(如查询绑定)