C预处理程序字符串化(再次) [英] C Preprocessor stringification (again)

查看:47
本文介绍了C预处理程序字符串化(再次)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在进行数字求值之后是否可以进行 stringification ?

Is it possible to have stringification after numeric evaluation?

这可以通过一个简单的例子更好地解释:

This is better explained with a simple example:

#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);

按照本文所述,将生成单行:

As written this generates the single line:

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

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

Is it possible, somehow, to generate char *sum = "3"; instead?

我怀疑这是不可能的,因为CPP是纯文本处理器(尽管它至少可以在条件下可以进行算术),但是我可能忽略了某些东西.

I suspect this is not possible because CPP is a purely text processor (altough it can do arithmetic, at least in conditionals), but I might have overlooked something.

推荐答案

在进行数字求值后是否可以进行字符串化处理?
Is it possible to have stringification after numeric evaluation?

是的.作为参考,下面是一些我将要使用的定义:

Yes. For reference here are some specific definitions I'll use:

  • 算术能够使用常见的原语(例如加,减,乘,除等)对数字执行计算.
  • 表达式使用常用运算符(如括号分组,中缀运算符+,-,*,/等)的算术语法表示法.
  • arithmetic The ability to perform calculations on numbers using common primitives such as adding, subtracting, multiplication, division, etc.
  • expression A grammatical representation of arithmetic using common operators such as parenthetical groupings, infix operators +, -, *, /, etc.

算术方法

鉴于这些定义,宏扩展无法评估表达式,但它们可以执行算术运算.您将使用宏,而不是运算符,每个宏都将从头实现算术.这是使用这种方法的pp用法:

Given these definitions, macro expansions cannot evaluate expressions, but they can perform arithmetic. Instead of the operators you would use macros, each of which would implement arithmetic from scratch. Here's a boost pp usage using this approach:

#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)

演示

使用这种方法,您可以简单地将宏扩展为结果;然后可以将结果字符串化.但是,您是在宏中而不是在运算符中实现算术本身,这需要大量的宏.因此,要实现这一目标,必须严格限制 的数字范围,或者使用可分解为宏评估的数字(例如,将20000表示为(2,0,0,0,0),而不是 20000 ).Boost pp算法使用前一种方法(适用范围从 0 256 ;是的,我意识到这是257个数字).

With this approach, you get to simply expand a macro to a result; that result can then be stringified. But you're implementing arithmetic itself in macros as opposed to operators, and that takes a lot of macros. So to pull this off, either your number ranges need to be severely limited, or you need to use numbers that are decomposable to macro evaluation (e.g., represent 20000 as (2,0,0,0,0) as opposed to 20000). Boost pp arithmetic uses the former approach (works with ranges from 0 to 256; yes, I realize that's 257 numbers).

表达方式

或者,您可以评估表达式.如前所述,预处理器可以在条件指令中对表达式求值.使用它作为原始函数,您可以梳理结果;例如,如果 EXPRESSION 扩展为表达式,则可以使用如下结构 #define D0 ,代表结果的单位数字:

Alternately, you can evaluate expressions. As noted, the preprocessor can evaluate expressions in conditional directives. Using that as a primitive, you can tease out the result; e.g., if EXPRESSION expands to your expression, you can #define D0, representing the unit digit of the result, using a construct like this:

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

然后,您可以类似地将 #define D1 用作十位的特定数字,为数百位的 D2 等,等等.然后将 RESULT 宏扩展到 ... D3 ## D2 ## D1 ## D0 .将整个内容包装成类似 evaluator.hpp 的内容,然后可以通过使用 #include"evaluator.hpp"将 EXPRESSION 定义为表达式来抽取任意表达式.对其进行评估,最后使用 RESULT 表示结果.使用这种方法,每个评估者"都需要为特定数字定义的特定Dx宏才能工作...以便其行为类似于变量",但会消耗整个评估者.

You can then similarly #define D1 to be the specific digit for the ten's place, D2 for the hundreds, etc... then have a RESULT macro expand to ... D3##D2##D1##D0. Wrap this entire thing into something like evaluator.hpp and you can pump an arbitrary expression in by defining EXPRESSION as your expression, using #include "evaluator.hpp" to evaluate it, and finally use RESULT to represent the result. With this approach each "evaluator" needs the specific Dx macros defined to the specific digits to work... so that behaves analogously to "variables", but consumes the entire evaluator.

Boost pp的每个评估程序都具有此功能,称为插槽",并提供5个插槽.因此,您必须添加 #include ,并且每个评估器一次只能存储一个结果...但是作为回报,您的范围不受 限制(大于原生范围),而您实际上是在评估表达式.这是通过boost pp使用这种方法的示例:

Boost pp has this capability with each evaluator known as a "slot", and provides 5 slots. So you have to pump with #include's, and each evaluator can only store one result at a time... but in return your range is not restricted (more than native ranges) and you're actually evaluating expressions. Here's an example of using this approach using 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))

演示

(手推式评估器此处(wandbox)可能值得一看,以了解其原理解释了上面的工作).

( Hand rolled evaluator here (wandbox) might be worth review to see how the mechanics explained above work).

TL; DR摘要

    • 算术
    • pro:完全通过宏调用求值con:宏而不是中缀运算符
    • con:范围受限制或使用其他文字表示形式
      • arithmetic
      • pro: evaluates entirely by macro invocation
      • con: macros instead of infix operators
      • con: either ranges are limited or uses alternate literal representations
        表达式
      • pro:计算实际表达式(中缀,组等)
      • pro:范围与本机范围一样开放,带有普通文字
      • con:需要`#include`来泵送通用机制
      • 缺点:评估程序的重用必须失去先前的结果
        expressions
      • pro: evaluates actual expressions (infix, groups, etc)
      • pro: ranges as open as native ranges, with ordinary literals
      • con: requires `#include` to pump generic mechanism
      • con: reuse of evaluator must lose previous result

      这篇关于C预处理程序字符串化(再次)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆