在C中有没有一种方法可以通过编程确定变量的值是在编译时还是在运行时计算的?
示例:
const double a = 2.0;
const double b = 3.0;
double c1 = a / b; // done at compile time (constant folding / propagation)
double c2 = *(volatile double*)&a / *(volatile double*)&b; // done at run time
compute_time_t c1_ct = compute_time(c1);
compute_time_t c2_ct = compute_time(c2);
assert(c1_ct == COMPILE_TIME);
assert(c2_ct == RUN_TIME);
在C中(如中,由语言标准定义(,不,没有办法。
然而,有一些编译器特定的方法可以让你真正接近于实现你想要的。正如@Nate Eldredge在评论中所指出的,最著名的是GCC和Clang中的内置函数__builtin_constant_p()
。
以下是GCC文档的相关摘录:
内置函数:
int __builtin_constant_p (exp)
您可以使用内置函数
__builtin_constant_p
来确定一个值在编译时是否已知为常量,因此GCC可以对涉及该值的表达式执行常量折叠。函数的参数是要测试的值。如果已知参数是编译时间常数,则函数返回整数1;如果未知参数是编译时常数,则返回0。返回0并不表示该值不是常数,而只是GCC无法用-O
选项的指定值证明它是常数。
请注意,此函数不保证检测所有编译时间常数,而只能检测GCC能够证明的编译时间常数。不同的优化级别可能会更改此函数返回的结果。
这个内置函数在glibc中被广泛用于优化目的(例如(,通常只有当它为1时,结果才可信,否则假设为非常数:
void somefunc(int x) {
if (__builtin_constant_p(x)) {
// Perform optimized operation knowing x is a compile-time constant.
} else {
// Assume x is not a compile-time constant.
}
}
使用您自己的示例:
const double a = 2.0;
const double b = 3.0;
double c1 = a / b; // done at compile time (constant folding / propagation)
double c2 = *(volatile double*)&a / *(volatile double*)&b; // done at run time
assert(__builtin_constant_p(c1));
assert(!__builtin_constant_p(c2));
你问,
在C中有没有一种方法可以通过编程确定该变量的值是在编译时还是在运行时计算的?
不,没有办法将这样的确定编码到严格一致的C程序的源中。
当然,C不要求以一种根据计算时间在值之间进行区分的方式对值进行系统标记,而且我从未听说或想象过任何C实现会这样做,因此这样的确定不能基于兴趣表达的值。此外,所有C函数参数都是通过值传递的,因此假设的compute_time()
不能作为函数实现,因为它只需要使用值。
compute_time()
也不能是宏,因为宏只能使用(预处理(标记,例如示例代码中的标识符c1
和c2
。这些对预处理器来说是不透明的;当根据C语义将它们求值为表达式时,它对赋予它们的值一无所知。
没有一个运营商能达到这个目的。
标准C没有提供其他替代方案,所以如果问题是关于C语言,而不是它的任何特定实现,那么故事就到此结束了。此外,尽管可以想象给定的C实现会提供compute_time()
或功能等效的扩展,但我不知道有任何这样的扩展