【问题标题】:How to call macro that uses token pasting?如何调用使用令牌粘贴的宏?
【发布时间】:2022-01-08 12:16:24
【问题描述】:

我正在尝试在C++ 程序中打印ffmpeg 版本。我看到在/libavutil/version.h 中有AV_VERSION 应该以x.x.x 的格式告诉版本号。

作为测试,我使用了一些随机数作为函数参数,如下所示:std::string version = AV_VERSION(3,4,2);。如果我使用文件中的LIBAVUTIL_VERSION_MAJORLIBAVUTIL_VERSION_MINORLIBAVUTIL_VERSION_MICRO,也会出现同样的错误。这实际上是我第一次尝试打印版本号。

如果我尝试打印std::cout << AV_VERSION(LIBAVUTIL_VERSION_MAJOR,LIBAVUTIL_VERSION_MINOR,LIBAVUTIL_VERSION_MICRO) << std::endl;,我得到的错误是invalid suffix '.2' on floating constantinvalid suffix '.101' on floating constant

我知道预处理器认为令牌是float,因此出现错误。您实际如何使用这种类型的宏功能?

那个宏在我上面提到的文件里,所以它一定是调用那个宏函数不报错的方法,认为是成熟的库,我猜其他库使用类似的东西打印版本号。

这是AV_VERSION在头文件中的定义以及我如何称呼它:

 #define AV_VERSION_INT(a, b, c) ((a)<<16 | (b)<<8 | (c))
 #define AV_VERSION_DOT(a, b, c) a ##.## b ##.## c
 #define AV_VERSION(a, b, c) AV_VERSION_DOT(a, b, c)

 #define AV_VERSION_MAJOR(a) ((a) >> 16)
 #define AV_VERSION_MINOR(a) (((a) & 0x00FF00) >> 8)
 #define AV_VERSION_MICRO(a) ((a) & 0xFF)

 #define LIBAVUTIL_VERSION_MAJOR  57
 #define LIBAVUTIL_VERSION_MINOR   9
 #define LIBAVUTIL_VERSION_MICRO 101

 #define LIBAVUTIL_VERSION_INT   AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \
                                            LIBAVUTIL_VERSION_MINOR, \
                                            LIBAVUTIL_VERSION_MICRO)
 #define LIBAVUTIL_VERSION       AV_VERSION(LIBAVUTIL_VERSION_MAJOR,     \
                                        LIBAVUTIL_VERSION_MINOR,     \
                                        LIBAVUTIL_VERSION_MICRO)

 int main()
 {
     std::string version = AV_VERSION(3,4,2);
     std::cout << AV_VERSION(LIBAVUTIL_VERSION_MAJOR,LIBAVUTIL_VERSION_MINOR,LIBAVUTIL_VERSION_MICRO) << std::endl;

     return 0;
 }

我可以跳过这个错误,但是当我正在尝试学习 C++ 时,我很确定我会找到更多这种类型的宏,所以当我面对它们时,没有必要避免现在学习它们。

提前致谢!

【问题讨论】:

    标签: c++ ffmpeg macros c-preprocessor token-pasting-operator


    【解决方案1】:

    您需要使用 stringize 扩展。由于预处理器的工作方式,这涉及到两个宏:

    #define STR(x) #x
    #define XSTR(x) STR(x)
    

    STR 将采用您提供的任何参数并将其设为字符串文字。

    XSTR将首先扩展其参数x,结果将是STR的参数。

    举例说明:

    • STR(LIBAVUTIL_VERSION) 会给"LIBAVUTIL_VERSION"
    • XSTR(LIBAVUTIL_VERSION) 会给"57.9.101"

    根据你的代码演示:

    int main()
    {
        std::string version1 = XSTR(LIBAVUTIL_VERSION);
        std::string version2 = XSTR(AV_VERSION(3,4,2));
        std::cout << version1 << "\n";
        std::cout << version2 << "\n";
        return 0;
    }
    

    输出:

    57.9.101
    3.4.2
    

    【讨论】:

    • 太好了。我查看了GNU macros,虽然在 Concatenation 部分没有说 stringize,但提到了 token pastingStringizing 部分。不幸的是没有在我的脑海中点击。非常感谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-29
    • 2011-04-15
    • 2012-02-18
    • 1970-01-01
    • 2017-03-05
    • 1970-01-01
    相关资源
    最近更新 更多