GCC将为运行时或编译输出留下固定值的算术吗?
Will GCC leave arithmetic with fixed values for run-time or compile the output?
我想知道GCC是否会在运行时留下固定值的算术,或者它是否会将其设置为它的答案,例如
const float halfPi = M_PI/2;
它会"煮沸"方程并设置
const float halfPi = 1.57079;
还是把算术留给运行时?
嗯…如果我们讨论积分,答案将是明确的是(在一般术语常数折叠下)。即使是冗长的计算也可以在编译时完成。这实际上是模板非类型参数求值和(现在)constexpr
变量所需要的。
对于浮点表示,随着计算变得更复杂,事情也变得更复杂了。问题是,对于相同的基本输入,不同大小(以及精度)的浮点表示将产生不同的结果。
要理解为什么,假设float
最多有5位精度:
5.0000 + 0.00001
-> 5.00001
-> 5.0000 (truncation to 5 digits)
5.0000 + 0.00001 + ... + 0.00001 (10 times)
-> 5.0000 + 0.00001 + ... + 0.00001 (9 times)
-> 5.0000 + 0.00001 + ... + 0.00001 (8 times)
-> ...
-> 5.0000
奇怪……对吧?如果编译是在运行时完成的,那么结果可能会根据是否使用寄存器(具有更大的位宽)而变化。
因此,常量折叠是否发生可能取决于所使用的优化标志集。例如,对于gcc,这可能由-freciprocal-math
控制(真的不知道)。因为即使编译器肯定可以这样做,您也可能告诉它不要这样做(不知不觉地)。
所以唯一确定的测试方法是检查编译器的输出;要么检查目标代码,要么要求编译器发出程序集。并且您需要检查该输出是否包含您使用的每个选项组合。
今天是你的幸运日,因为你发现Agner Fog和他的惊人的深度c++
手册!如果你看一下这篇文章的8.2
节,你会发现基本上所有的编译器都能进行常量折叠。
虽然要确保它在编译器选项的特定情况下确实发生,但您应该按照上面的建议检查程序集输出(使用-S
)。我喜欢把像asm("MY_LABEL:");
这样的东西放在代码附近,以便于找到,但请记住,这可以改变代码的含义,因此编译器如何解释它。在这种情况下,我不相信它会改变什么。
相关文章:
- 为什么即使使用-cudart-static进行编译,库用户仍然需要链接到cuda运行时
- 是否可以在编译时初始化数组,以便在运行时不会花费时间?
- 在运行时解析函数,而不是在编译C++解析函数
- 在编译时,C++项目抛出错误 C2228,这是预期的,因为控件在运行时未达到该点
- 在编译时为运行时设置环境变量
- 运行时检查失败 #0 用于运行时重新编译
- std::tuple 可以根据其值在编译时/运行时排序吗?
- C++项目编译强制使用 /clr 选项,尽管在没有公共语言运行时支持的情况下执行它
- 在编译时而不是运行时创建一个由两个字节组成的值
- scanf() 的宽度说明符 - 要使用的字符长度在编译时不固定,仅在运行时确定.如何使其可变?
- 如何在运行时编译 c++ 代码(如 Python 中的 eval)
- C 构造函数运行时/编译时间
- 有没有办法在运行时编译C++代码
- visual在源代码中是否有预定义的#define或其他方式来了解它是为C++/CX Windows运行时编译的
- 关于运行时/编译时和堆/堆栈的说明
- 如何在运行时编译C++程序并将其链接到DLL中
- 将编译器添加到程序中进行运行时编译的好方法是什么?
- 我们可以使用“LoadLibrary”让我们的应用程序用Visual Studio 2010和静态运行时编译吗?
- 运行时/编译时初始化char***
- 在混合运行时/编译时条件下调度标记