【问题标题】:C Preprocessor stringification (again) [duplicate]C预处理器字符串化(再次)[重复]
【发布时间】:2019-12-06 08:58:25
【问题描述】:

是否可以有stringification数值评估之后?

用一个简单的例子可以更好地解释:

#define A 1
#define B 2
#define SUM (A + B)

#define STR_IMPL_(x) #x
#define STR(x) STR_IMPL_(x)

char *sum = STR(SUM);

正如所写,这会生成单行:

char *sum = "(1 + 2)";

是否有可能以某种方式生成char *sum = "3";

我怀疑这是不可能的,因为 CPP 是一个纯文本处理器(尽管它可以做算术,至少在条件语句中),但我可能忽略了一些东西。

【问题讨论】:

  • 我最近在找这个,我发现的只是一个使用 C++ 模板的方法。
  • 达到极限是可能的。 Boost PP 支持类似的东西。由于它是一个仅预处理头文件的库,因此您可能会使用它。
  • @GSerg:链接的答案并没有真正回答问题(涉及纯 CPP 数学,而不是其字符串化)。答案中有一些明显有趣的指针,但它们似乎已经死了:(
  • 这个问题的答案实际上是:不,你不能以对你的情况有意义的方式来做这件事,因为你不能有通用的预处理器代码。您将不得不编写一些 #if (x) == 3 #define FOO "3" #endif 的风格,或者使用非标准扩展。

标签: c c-preprocessor stringification


【解决方案1】:
是否可以在数值评估后进行字符串化?

是的。以下是我将使用的一些具体定义供参考:

  • 算术能够使用常见的原语(例如加法、减法、乘法、除法等)对数字执行计算。
  • 表达式 使用常用运算符(如括号分组、中缀运算符 +、-、*、/ 等)的算术语法表示。

算术方法

鉴于这些定义,宏扩展不能计算表达式,但它们可以执行算术运算。您将使用宏而不是运算符,每个宏都将从头开始实现算术。这是使用这种方法的提升 pp 使用情况:

#include <boost/preprocessor/arithmetic.hpp>
#include <boost/preprocessor/stringize.hpp>

#define A 1
#define B 2
#define SUM BOOST_PP_ADD(A, B)
BOOST_PP_STRINGIZE(SUM)

Demo

使用这种方法,您可以简单地将宏扩展为结果;然后可以将该结果字符串化。但是你在宏而不是运算符中实现算术本身,这需要很多宏。所以要实现这一点,要么您的数字范围需要严格限制,或者您需要使用可分解为宏观评估的数字(例如,将 20000 表示为 @987654326 @ 而不是 20000)。 Boost pp 算法使用前一种方法(适用于从 0256 的范围;是的,我意识到这是 257 个数字)。

表达方式

或者,您可以评估表达式。如前所述,预处理器可以评估条件指令中的表达式。将其用作原语,您可以梳理出结果;例如,如果 EXPRESSION 扩展为您的表达式,您可以 #define D0,表示结果的个位,使用如下构造:

#if   ((EXPRESSION)%10)==9
#define D0 9
#elif ((EXPRESSION)%10)==8
#define D0 8
...

然后您可以类似地将#defineD1 用作十位的特定数字,将D2 用作百位等...然后将RESULT 宏扩展为... D3##D2##D1##D0。将整个事情包装成evaluator.hpp 之类的东西,您可以通过将EXPRESSION 定义为您的表达式,使用#include "evaluator.hpp" 对其进行评估,最后使用RESULT 来表示结果,从而输入任意表达式。使用这种方法,每个“求值器”都需要为特定数字定义的特定 Dx 宏才能工作……因此其行为类似于“变量”,但会消耗整个求值器。

Boost pp 具有此功能,每个评估器称为“插槽”,并提供 5 个插槽。因此,您必须使用#include 进行抽水,并且每个评估者一次只能存储一个结果......但作为回报,您的范围不受限制(超过原生范围)并且您重新实际评估表达式。下面是一个使用 boost pp 的例子:

#include <boost/preprocessor/slot/slot.hpp>
#include <boost/preprocessor/stringize.hpp>

#define A 1
#define B 2
#define SUM (A+B)

#define BOOST_PP_VALUE SUM
#include BOOST_PP_ASSIGN_SLOT(1)

BOOST_PP_STRINGIZE(BOOST_PP_SLOT(1))

Demo

(编辑:手卷评估器here (wandbox) 可能值得回顾一下,看看上面解释的机制是如何工作的)。

TL;DR 总结

    • 算术
    • pro:完全通过宏调用进行评估
    • con:宏而不是中缀运算符
    • con:要么范围有限,要么使用替代文字表示
    • 表达式
    • pro:计算实际表达式(中缀、组等)
    • pro:范围与本地范围一样开放,使用普通文字
    • con:需要 `#include` 来泵送通用机制
    • con:重用评估器必须丢失以前的结果

【讨论】:

  • 这是标记为 C。Boost 是非标准 C++。
  • @Lundin "该库支持C++ 和 C 编译。它不依赖于任何其他 Boost 库,因此可以用作独立图书馆。” source
【解决方案2】:
#include <boost/preprocessor/arithmetic/add.hpp>

char* sum = STR(BOOST_PP_ADD(A,B));

【讨论】:

  • 这应该适用于“Plain C”还是需要 C++?
  • ZioByte:正如@StoryTeller 提到的,boost pp 是一个仅限预处理器的库; C++ 和 C 共享相同的 cpp,所以可以在 C 中工作 (demo);在底部注意,我在这里使用 gcc 而不是 g++,这并不重要,因为它在预处理器处停止。
猜你喜欢
  • 1970-01-01
  • 2011-11-15
  • 1970-01-01
  • 2011-10-22
  • 1970-01-01
  • 2019-06-21
  • 1970-01-01
  • 2016-08-14
相关资源
最近更新 更多