C宏在编译时评估

Dan*_*jel 3 c c-preprocessor

我需要一个可以在编译时进行评估的宏,例如:

#define FIND_RANGE(x) \
if x>16 \
32 \
elif x>8 \
16 \
elif x>4 \
8 \
elif x>2 \
4 \
elif x>1 \
2 \
else \
1 \
endif \
Run Code Online (Sandbox Code Playgroud)

所以代码

#define S1 FIND_RANGE(7)
unsinged int i = S1;
Run Code Online (Sandbox Code Playgroud)

将被发送到编译器

unsinged int i = 8;
Run Code Online (Sandbox Code Playgroud)

是否可以完成这个简单的算法,以便在编译时进行评估?

Grz*_*ski 7

虽然C没有constexpr函数,但GCC和Clang都可以在编译时评估简单函数-O1.相关的优化称为常数折叠.

以下C代码:

#include <stdio.h>

static inline unsigned int findRange(unsigned int x)
{
    if (x > 16)
        return 32;
    else if (x > 8)
        return 16;
    else if (x > 4)
        return 8;
    else if (x > 2)
        return 4;
    else if (x > 1)
        return 2;
    return 1;
}

int main(void)
{
    unsigned int i = findRange(7);
    printf("%u\n", i);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

结果到x86-64汇编代码(参考:godbolt.org/g/kVYe0u):

main:
        sub     rsp, 8
        mov     esi, 8
        mov     edi, OFFSET FLAT:.LC0
        mov     eax, 0
        call    printf
        mov     eax, 0
        add     rsp, 8
        ret
Run Code Online (Sandbox Code Playgroud)

如您所见,调用findRange由值替代,该值在编译时计算.

即使findRange被定义为具有外部链接的正常(非内联)函数,这也可以工作.

  • @Danijel:MM的建议很简洁,因为它允许将条件打包到单个表达式中,而不是多个语句中。我的答案的目的是证明,它不再是必要的,因为现代编译器将优化代码(产生最终结果),同时它更具可读性和安全性(例如考虑“SCALE(x++)”)。 (2认同)