【问题标题】:In C can you pass a macro with multiple values to a function在 C 中,您可以将具有多个值的宏传递给函数吗
【发布时间】:2020-07-07 03:08:47
【问题描述】:

我有一个消息传递函数,它接受可变数量的参数,因为它以与 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" 与匹配的调用MSG(MSG_CONEST, server_ip);),所以摆脱它不是一种选择。我只是在寻找解决此问题的最佳方法,我知道很多人建议远离预处理器,但这是我想到的最佳解决方案。

【问题讨论】:

  • __VA_OPT__(,)
  • 另一个问题是,如果你这样做#define MSG_INIT 0000, "%s INITIALIZED SUCCESSFULLY",那么 MSG_INIT 只是一个参数。所以也许你需要#define MSG(...) message(__FILE__, __LINE__, __VA_ARGS__)

标签: macros c-preprocessor


【解决方案1】:

我知道很多人建议远离预处理器...

我想知道为什么会这样。是否可能出于同样的原因,您不得不问这个问题? :-)

老实说,预处理器应该几乎仅限于包含头文件和进行条件编译。它曾经用于的任何其他东西,例如:

#define RC_OK    0
#define RC_NOMEM 1

#define HALF_OF(x) x / 2

用枚举或函数做得更好。

类似函数的宏的时代应该过去了,特别是因为现代编译器可以很容易地优化大多数手工编写的代码,并且不会像@上面的987654322@宏(不要用它,我特意弄了个bug来说明一点)。

它实际上只是一个文本替换的东西,它理解词汇元素,但不是 C 的完整语法。事实上,你必须执行我所说的“宏观体操”才能让它做任何事情而不是简单的东西有足够的理由避开。为此使用函数,它会让你的生活更轻松。


很抱歉没有解决您的特定问题,我只是认为使用预处理器的任何解决方案充其量只是半生不熟。但是有很多关于 SO 的先例可以回答“我如何 X?”这个问题。用“不要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

【讨论】:

  • 欣赏建议。我可能最终会避免同时定义两个变量的宏,但是我有一个后续问题。我使用预处理器宏的主要目的是为我传递__FILE____LINE__ 参数。 (我在更多的功能中使用它,而不仅仅是这个消息示例)我只是使用这些来打印重要功能中的程序流程。这是我没有经常讨论的问题,但是您是否建议也避免这种情况,并且每次我调用该函数时都将其传递,或者这是否更有效/更安全地使用预处理器?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-01-20
  • 1970-01-01
  • 2019-12-04
  • 1970-01-01
  • 2013-04-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多