且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

用宏包装函数(不重命名)C

更新时间:2023-12-01 08:42:34

通常不需要重命名宏包装函数,因为在宏扩展内,宏的名称不会扩展.

There's normally no need to rename macro-wrapped functions because inside the expansion of a macro, the macro's name is not expanded.

这是直接来自C11标准的示例:

Here's an example straight from the C11 standard:

#define cbrt(X) _Generic((X),               \
                        long double: cbrtl, \
                        default: cbrt,      \
                        float: cbrtf        \
                        )(X)

当然,如果您具有#include <tgmath.h>,则会遇到问题,因为在这种情况下,您已经具有类型通用的宏,例如上面的宏,并且您将无法重新定义sqrt (除非您#undef它).而且必须先#include <math.h>定义该宏.

Of course, you'll run into problems if you've #include <tgmath.h> because in that case you'll already have type-generic macros, such as the above, and you won't be able to redefine sqrt (unless you #undef it). And you must #include <math.h> before defining that macro.

即使如此,您还是要踩在薄冰上.该标准保留了标准库函数的名称,并坚持认为(§ 7.1.3/2):

Even so, you're treading on thin ice. The standard reserves the names of standard library functions, and insists that (§7.1.3/2):

如果程序在保留它的上下文中声明或定义标识符(而不是7.1.4允许),或者将保留标识符定义为宏名,则行为未定义.

If the program declares or defines an identifier in a context in which it is reserved (other than as allowed by 7.1.4), or defines a reserved identifier as a macro name, the behavior is undefined.

参考的第7.1.4节确实允许您#undef一个类似于函数的宏,该宏遮盖了标准库函数,但是对我来说尚不清楚您是否可以随后重新定义它. YMMV.

The referenced section 7.1.4 does allow you to #undef a function-like macro which shadows a standard-library function, but it is not clear to me that you are allowed to subsequently redefine it. YMMV.

如果您想使用_Generic来调用包装函数,则仍然可以在不重命名原始函数的情况下使它起作用.例如:

If you wanted to use _Generic to call a wrapper function, you can still make that work without renaming the original function. For example:

#include <nanny.h>

/* In this file, you can't call nanny(char), and if you call it
 * with an unsigned argument, we'll insert an additional check
 */

#define nanny(X) _Generic((X), int: nanny, unsigned:nanny_wrapper)(X)

int nanny_wrapper(unsigned x) {
  assert(x < INT_MAX);
  /* The redundant parentheses prevent macro expansion */
  return (nanny)(x);
}