【问题标题】:C macro produces different result using literal vs variableC宏使用文字与变量产生不同的结果
【发布时间】:2016-08-12 12:19:05
【问题描述】:

我有以下 C 程序:

#include <stdio.h>
#include <math.h>

#define LOG2(x) ((int)( log((double)(x)) / log(2) ))

int main() {

    int num = 64;
    int val1 = LOG2(num);
    int val2 = LOG2(64);

    printf("val1: %d, val2 %d\n", val1, val2);

    return 0;
}

哪些输出:

val1: 5, val2: 6

为什么当我将它与变量一起使用时,这个宏会产生不同(和错误)的答案,但当我直接输入 64 时却能正常工作?

不管这实际上是否是获取日志基数 2 的好方法,是什么导致了这种行为?有什么办法可以让这个宏与变量一起正常工作? (我所有的输入都是 2 的精确幂)

【问题讨论】:

  • 对我来说,两个都显示5ideone.com/QSVioZ
  • 对我来说,两者都是6。请问您使用的是哪台机器和编译器?
  • 问题似乎是您在宏中对(int) 的转换。删除强制转换允许 LOG2 返回与声明为 double 的值相同的值。
  • 你使用的是哪个编译器

标签: c types macros


【解决方案1】:

从数学上讲,这是一种计算以 2 为底的对数的好方法,但由于 log(val) 和 log(2) 都是长而杂乱的分数,除法的结果不太可能结束最高为 5.999,这将截断为 5。我建议四舍五入,特别是如果您知道输入将始终是 2 的幂。

(但是为什么你对常量和变量得到不同的答案?这是一个很好的问题,我不确定答案。通常答案是当涉及常量时,编译器能够执行一些/所有计算都在编译时进行,但通常编译器最终使用与运行时环境略有不同或显着不同的浮点运算.但我不会想到编译器会在编译时解释像log()这样的函数-时间常数折叠。)


另外,一些 C 库有一个 log2() 函数,它应该会给你完美的答案,但我不知道这个函数有多标准。

【讨论】:

  • log2 在 C99 中添加
  • 我要补充一点,使用 round() 是一个很好的解决方案(而不是滚动自己的舍入)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-09
  • 1970-01-01
  • 1970-01-01
  • 2015-04-24
相关资源
最近更新 更多