在C中命名宏有限制/问题吗?

d3L*_*d3L 2 c macros naming

我想拥有可以包含可选参数的函数.当然这不能用C来完成,但它有可能带有一些宏观魔力:

#define _macroWith1Arg(_0, _1, macroName, ...)          _ ## macroName
#define _macroWith2Args(_0, _1, _2, macroName, ...)     _ ## macroName
#define _macroWith3Args(_0, _1, _2, _3, macroName, ...) _ ## macroName

#define macroWith1Arg(macroName, ...)               _macroWith1Arg(_0, __VA_ARGS__, macroName ## _1, macroName ## _0)(__VA_ARGS__)
#define macroWith2Args(macroName, ...)              _macroWith2Args(_0, __VA_ARGS__, macroName ## _2, macroName ## _1, macroName ## _0)(__VA_ARGS__)
#define macroWith3Args(macroName, ...)              _macroWith3Args(_0, __VA_ARGS__, macroName ## _3, macroName ## _2, macroName ## _1, macroName ## _0)(__VA_ARGS__)

#define _sum_1(_1)      (_1)
#define _sum_2(_1, _2)  (_1) + (_2)
#define sum(...)        macroWith2Args(sum, __VA_ARGS__)

fprintf(stderr, "%d ", sum(1)); // Prints 1
fprintf(stderr, "%d ", sum(1, 2)); // Prints 3
Run Code Online (Sandbox Code Playgroud)

我喜欢它的外观:它看起来像一个带有可选参数的普通函数.但这样做的缺点是你不能拥有一个像宏一样的函数指针sum.所以我听说你应该将名称大写以将其显式标记为宏(如"SUM")以避免混淆.

现在我的问题是:这个命名约定是否真的有必要,我的意思是标准C用它来做errno(例如至少在我的平台上)?我认为大多数IDE都可以识别宏并将其突出显示.我真的很想听听你对此的看法.

编辑:

我找到了一种方法来实现,你可以采取一个函数指针:

int my_sum(int, int);
#define _sum_1(_1)     my_sum(_1, 0)
#define _sum_2(_1, _2) my_sum(_1, _2)
#define sum(...)       macroWith2Args(sum, __VA_ARGS__)
int (*sum)(int, int) = my_sum;

// Use it as a "function":
fprintf(stderr, "%d ", sum(1, 2)); // Prints 3
// Take a function pointer:
int (*sumptr)(int, int) = sum;
fprintf(stderr, "%d ", sumptr(1, 0)); // Prints 1
Run Code Online (Sandbox Code Playgroud)

Jen*_*edt 5

在C(预处理器是其中的一部分)中,您可以比编辑中建议的更多:宏和函数可以具有相同的名称.虽然在应用程序代码中很少这样做,但C库本身可以拥有它.这里标准函数可以作为宏实现,但是也必须提供具有相同名称的符号.

因此标准本身并不遵守宏名称应该全部大写的规则.

我认为,如果你在实施中小心谨慎

  • 使用一组完整的参数调用宏只是预处理器阶段的标识
  • 提供的有效函数声明具有相同的名称

那么使用小写标识符应该没有问题.

通过这个你确保

  • 为您的函数重复原型仍然是一个有效的操作
  • 取一个函数指针可以毫无问题地完成

并且在你所有的实现中表现得好像你的宏在哪里有一个函数.

顺便说一句,您发布的代码不符合标准.以下划线开头的标识符保留在文件范围中.这不是惯例,而是必要的.