【问题标题】:XCode: Initializer element is not a compile-time constantXCode:初始化器元素不是编译时常量
【发布时间】:2014-02-18 17:45:18
【问题描述】:

我正在使用 XCode 用 C 语言编写程序。我很少使用C,通常我使用C++。我以前从未使用过 XCode。

编译错误很简单,以下代码行没有被编译器视为编译时常量。

const double PI = 4.0 * atan(1.0);
const double TAU = 8.0 * atan(1.0);

我确信这在 C++ 11 中是允许的,尽管我不能肯定,因为我几个月前最后一次使用它。

我的猜测是 XCode 编译器/C 标准不允许以这种方式计算常量。

我可以使用其他替代方法吗?我不太喜欢“定义”的替代方案......

#define PI 4.0 * atan(1.0);

因为这会(可能?)导致不必要的运行时开销。

【问题讨论】:

  • 为什么不使用来自math.hM_PI 或者只使用3.141592653589?那应该是doubleprecision。

标签: c xcode constants compile-time-constant


【解决方案1】:

编译器不会将以下代码行视为编译时常量。

编译器是对的,因为它们不是编译时常量:它们都调用标准 C 库的运行时部分。

我不太喜欢“定义”替代方案...

没错,#define 不是替代方案,因为它会强制在您拥有的每个表达式中重新计算一个常量。

我可以使用其他替代方法吗?

当然 - 您可以使用 M_PI 定义 π 常量 *,使用 2*M_PI 定义 TAU

const double TAU = 2 * M_PI;

我确信这在 C++ 11 中是允许的

这是正确的:与 C 不同,C++ 并不要求初始化器是编译时常量。

怎么叫atan()不被允许,而数学运算2 * M_PI却被允许?

这是因为标准要求编译器在编译期间对常量表达式执行所有数值运算。但是,单个运行时调用,例如 atan(...),会“毒化”整个事物,因此编译器将尽可能多地求值,但表达式仍将是运行时表达式,而不是编译时常量。

* 不是标准的,但是很多库还是定义了。

【讨论】:

  • 为什么我可以在 C++ 中这样做? M_PI 听起来不像是一个死板的解决方案……它是什么,它有多少位精度?
  • 其实还有一个问题:为什么不允许调用atan(),却允许数学运算2 * M_PI?
【解决方案2】:

这在 C 中是不允许的。与 C++ 不同,C 要求全局变量由 编译时 常量初始化。 atan(1.0) 不是编译时常量,因为它需要在运行时调用函数 atan()

简单的解决方案是不要调用atan(),只需使用 pi 和 tau 的实际数值作为初始化器:

const double PI = 3.141592653589793;
const double TAU = 2*PI;

一些数学库也已经为你提供了常量M_PI,所以你可以这样做:

const double PI = M_PI;

但这不是标准 C(C89 或 C99),所以不要依赖所有具有该常量的实现。

【讨论】:

  • 啊,原来是一种微妙的语言。如果 C2014(存在这样的事情吗?)扩展语言以允许这样做,那就太好了。
猜你喜欢
  • 2011-09-02
  • 1970-01-01
  • 2012-08-31
  • 1970-01-01
  • 2012-03-22
  • 1970-01-01
  • 2015-07-21
  • 1970-01-01
相关资源
最近更新 更多