【问题标题】:Using C preprocessor concatenation to get number in exponential notation使用 C 预处理器连接以指数表示法获取数字
【发布时间】:2012-07-12 13:40:50
【问题描述】:

为什么要打码:

#define EXPONENT(num, exp) num ## e ## exp
EXPONENT(1,1)
EXPONENT(1,-1)
EXPONENT(1,+1)

预处理后变为:

1e1
1e- 1
1e+ 1

并没有进入

1e1
1e-1
1e+1

? 我怀疑这可能是因为 -1,+1 被解析为两个标记(?)。但是,在那种情况下如何获得后者的结果呢?

【问题讨论】:

  • 我认为你需要另一个级别的间接...见这里stackoverflow.com/questions/1489932/…
  • 我认为在尝试与另一个#define 的值连接时,需要另一个级别的间接,但这里不是这种情况。
  • @JoSo:嗯。对我不起作用(GCC 4.1.2、4.3.4 或 4.5.1)!
  • 我用 gcc 4.6.3 和 clang 3.0 检查过
  • @KrzysztofWitkowski:奇怪!仍在研究中。

标签: concatenation c-preprocessor


【解决方案1】:

你是对的,-1+1 是两个预处理标记,因此只有第一个被粘贴到 e

对我来说,

#define EXPO(num, sign, ex) num ## e ## sign ## ex

EXPO(1,,1)
EXPO(1,-,1)
EXPO(1,+,1)

使用 gcc-4.5.1。

【讨论】:

  • 这行得通。然而,为了解决我的问题,你改变了它的描述;-) 我需要一个只接受两个参数的宏,数字和指数......
  • 如果这是一个不可更改的要求,我不知道该怎么做。这可能是不可能的。
【解决方案2】:

我认为您遇到的问题被认为是未定义的行为。每gcc 4.3.2 documentation on concatentation

但是,不能一起形成有效令牌的两个令牌不能 粘贴在一起。例如,您不能将 x 与 + in 连接起来 无论是订单。如果您尝试,预处理器会发出警告并发出 两个令牌。是否在标记之间放置空格是 不明确的。在复杂中发现 ## 的不必要用法是很常见的 宏。如果您收到此警告,很可能您可以简单地 删除`##'。

另请参阅 SO 上的 this answer,它表现出同样的问题。

编辑:

我设法让它工作,但你需要两个宏来表示 + 和 -

#define E(X) 1e-##X
int main()
{
  double a = E(10); // expands to 1e-10
  printf("%e", a);
  return 0;
}

【讨论】:

  • 谢谢。这是否意味着不可能用 C 预处理器解决我的问题?
  • @kwitek:您是否尝试过该答案中最后一个代码示例的变体?
  • 是的。 #define EXPO(x, y) x e y 留下空格,#define EXPO(x, y) xeb 产生字符串 xeb ;(
【解决方案3】:
#include <stdio.h>
#include <stdlib.h>

#define EXPONENT(num, exp) atof(#num "e" #exp)

void main(){
    double x = EXPONENT(1,-1); 
    printf("%f", x);
}

【讨论】:

  • 我觉得丹尼尔的建议更好。
猜你喜欢
  • 2015-09-13
  • 1970-01-01
  • 2011-04-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-28
  • 1970-01-01
相关资源
最近更新 更多