C 宏使用文字与变量产生不同的结果

标签 c types macros

我有以下 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 的精确幂)

最佳答案

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

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


此外,一些 C 库有一个 log2() 函数,它应该可以为您提供完美的答案,但我不知道该函数的标准程度如何。

关于C 宏使用文字与变量产生不同的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36733321/

相关文章:

C 程序永远等待 scanf

c - C 中涉及常量的算术表达式类型

c++ - DWORD 和 DWORD32 之间的区别

c++ - 调用使用 __LINE__ 构建的函数名称

c - 具有带括号结构的宏

c++ - 如何在 c/c++ 的命令行程序中创建 --help 选项?

c - 为什么 srand 创建相同的数字?

可以将 unsigned int 位值复制为 float,但 float 值未正确返回到调用函数

scala - 当参数不符合类型约束时,为什么这个 Scala 函数会编译?

emacs - 在 emacs 中查询替换宏?