C预先计算的表达式

时间:2014-12-30 07:24:42

标签: c

我想根据参数是否超出系统限制的函数来切换库例程中的处理,例如(input-1)< = sqrt(LONG_MAX)

在我看来,我有三种选择在C中实现它:

  1. 评估每个库调用中的函数。虽然有些编译器可能会使用常量参数优化math.h函数调用,但价格昂贵。
  2. 将函数调用的结果定义为预处理器宏。查看glibc limits.h,这将需要两个基于__WORDSIZE值的#defines。我认为这不是便携式的
  3. 创建一个全局变量,该变量设置为初始化程序中函数的结果。这要求库用户始终在任何其他库例程之前运行init例程
  4. 我真的不喜欢这些方法。如果之前没有运行,则在1和3之间的折衷是在内部运行init。这使用户无需执行此操作,并将运行时开销减少到一个布尔值检查。

    是否有更优雅的解决方案?

3 个答案:

答案 0 :(得分:3)

"优雅"并不是一个定义明确的术语,你最好指定一些更可衡量的东西,比如" speed"。

如果速度确实是目标,那么系统参数是在运行时不会改变的参数,您可以拥有一个便携式解决方案,如:

#undef SQRT_LM
#if LONG_MAX == 64
    #define SQRT_LM 8
#endif
#if LONG_MAX == 256
    #define SQRT_LM 16
#endif
: : :
#ifndef SQRT_LM
    #error Weird LONG_MAX value, please adjust code above.
#endif

然后您的代码可以简单地使用SQRT_LM作为常量值。

1/3组合,类似于:

void doSomething(int x) {
    static long sqrt_lm = -1;
    if (sqrt_lm == -1)
        sqrt_lm = sqrt(LONG_MAX);
    // Now can use sqrt_lm freely
}

并不像强制用户明确调用init函数那样高效,因为上面的代码仍然需要在每次调用时执行if

但是,如上所述,它实际上取决于你的意思"优雅"。我倾向于首先优化可读性,如果它成为一个严重的问题,只会担心性能。

答案 1 :(得分:1)

在函数中使用静态变量:

void foo(int input)
{
    static const long limit = __builtin_sqrt(LONG_MAX);

    assert(input < limit);
}

所以limit仅在第一次执行函数时计算。这要求函数是一个常量表达式,这就是我使用GCC __builtin_sqrt()的原因;常规sqrt()将被拒绝(至少由海湾合作委员会)。

答案 2 :(得分:1)

不是(输入-1)&lt; = sqrt(LONG_MAX)与输入&lt; = sqrt(LONG_MAX)+ 1相同,它看起来就像一个值与常量的简单比较。