【问题标题】:Preprocessor Macro Translation预处理器宏翻译
【发布时间】:2019-01-10 22:39:13
【问题描述】:

在.NET Core CLR源代码中,我找到了如下宏定义:

#define CORECLR_HOSTING_API(function, ...) \
  extern "C" int function(__VA_ARGS__); \
  typedef int (*function##_ptr)(__VA_ARGS__)

CORECLR_HOSTING_API(coreclr_shutdown,
            void* hostHandle,
            unsigned int domainId);

cmets 说 this 定义了一个函数原型和一个函数指针。有没有人能够“翻译”这个非宏版本的样子?也就是说,如果它没有包裹在宏中,它会是什么样子? “*function##_ptr”部分让我很困惑......

【问题讨论】:

  • 如果它显示extern "C" …,那么代码是为 C++ 而不是为纯 C 编译器设计的。

标签: c c-preprocessor preprocessor


【解决方案1】:

## 操作符是串联的,在这里使用是因为function_ptr 是一个有效的标识符,所以预处理器不会知道替换它的function 部分。那么,预处理的结果是:

extern "C" int coreclr_shutdown(void* hostHandle, unsigned int domainId);
typedef int (*coreclr_shutdown_ptr)(void* hostHandle, unsigned int domainId);

(为了便于阅读,我对空格进行了模数更改)

【讨论】:

    【解决方案2】:

    有时有编译器选项允许查看语句的处理器输出。如果没有,总是有godbolt,您可以在其中使用-E 选项和gcc 编译器查看(我添加的换行符):

    extern "C" int coreclr_shutdown(void* hostHandle, unsigned int domainId); 
    typedef int (*coreclr_shutdown_ptr)(void* hostHandle, unsigned int domainId)
    

    宏扩展中的## 表示串联。所以function ## _ptr 意味着将function 后面的字符串(它是宏参数)与字符串(文字)_ptr 连接起来。例如:

    #define CONCAT(a,b) a ## b
    CONCAT(abc, def) // will be translated by preprocessor into abcdef
    

    【讨论】:

    • 奇怪的是,godbolt 在宏调用后排除了分号。无论如何,这似乎是一个不错的资源。
    • @CraigMeier 这是因为 Godbolt 认为它正在使用 -E 打印程序集,因此它将第一个 ; 之后的所有内容视为注释并删除更多 ; 单击绿色勾号查看确切的命令。它隐式添加了-S
    • 能够看到在 gcc 中很有用,我使用适用于 Linux 的 Windows 子系统和构建必需的包,允许我测试至少最小的跨平台支持。感谢您的提示!
    猜你喜欢
    • 1970-01-01
    • 2015-04-15
    • 2015-07-31
    • 1970-01-01
    • 2010-09-19
    • 2020-02-09
    • 1970-01-01
    • 2011-01-26
    相关资源
    最近更新 更多