2015-04-02 71 views
3

我想了解如何按位运算由C/C++编译器处理。 具体来说,我说的是用gcc编译的C,但我相信这个问题比这个更普遍一些。在C/C++编译时按位运算

无论如何,假设我有一个定义的宏如下:

#define SOME_CONSTANT 0x111UL 
    #define SOME_OFFSET 2 
    #define SOME_MASK  7 
    #define SOME_VALUE ((SOME_CONSTANT) << (SOME_OFFSET)) & (SOME_MASK) 

    static inline void foo() { printf("Value: %lu#n", SOME_VALUE); } 

所有SOME_VALUE的成分是常数,它们是在编译时已知的所有。

所以我的问题是:gcc会在编译时评估SOME_VALUE,还是只会在运行时完成? 如何检查gcc是否支持这种优化?

+4

看看汇编语言输出(在gcc中有命令行选项 - '-S')。预处理器应该替换文本,因此编译器是否优化了剩余的内容。这应该。 – sje397 2015-04-02 07:59:49

+4

这被称为“常量折叠”,您可以确信任何现代编译器都会在编译时执行此操作。 – Sneftel 2015-04-02 08:00:14

+0

你可能想阅读§6。6(“常量表达式”)在ISO/IEC 9899:1999中解决了这个问题。或者[此概述](http://en.cppreference.com/w/c/language/constant_expression)。 – 2015-04-02 08:11:37

回答

3

是,GCC将优化这个,因为它是一个完全常量表达式。

要在汇编代码检查这一下,例如使用此工具https://gcc.godbolt.org/

#include <stdio.h> 

#define SOME_CONSTANT 0x111UL 
#define SOME_OFFSET 2 
#define SOME_MASK  7 
#define SOME_VALUE ((SOME_CONSTANT) << (SOME_OFFSET)) & (SOME_MASK) 

void foo() { printf("Value: %lu#n", SOME_VALUE); } 

我只好稍微修改代码否则GCC优化掉了整个事情,并没有留下!

.LC0: 
    .string "Value: %lu#n" 
foo(): 
    movl $4, %esi 
    movl $.LC0, %edi 
    xorl %eax, %eax 
    jmp printf 
1

会的gcc编译时

我不知道你,我的的确

如何检查一个gcc是否支持这样的优化评估SOME_VALUE?

我用-S标志生成汇编代码,并检查它

movl $4, %esi 
+0

检查simurg的答案。你的编译器不会优化。它是预处理器。另外我不认为这个运营商想要开始一个关于这个问题的调查。 – Matthias 2017-02-23 08:16:46

5

你的编译器不知道SOME_VALUE。 C代码首先通过C预处理器传递给C编译器。

gcc -E code.c

你会看到,输入到C编译器的真正的代码是:

int main(void) { 
printf("Value: %lu#n", ((0x111UL) << (2)) & (7)); 
return 0; 
} 

因此问题变成了“是否可以通过运行gcc作为看到C预处理器的输出C编译器GCC优化((0x111UL) << (2)) & (7)“,答案是肯定的(正如其他答复者通过查看生成的汇编代码证明的那样)。

+0

谢谢!我已经接受了另一个答案,但你同样有帮助:) – kliteyn 2015-04-02 12:14:42

-2

正如其他人回答,是的,它会。但是要考虑不是要求;如果你想确定这一点,只需预先计算它,因为你有所有的元素来做到这一点。

+0

任何投票的动机? – edmz 2015-04-02 08:47:31

+0

编译器不是*必需的*来优化,当然,但是*为什么*它会选择不,除非它被指示('-O0')?考虑到恒定折叠是可用的最基本的优化之一? – 2015-04-02 09:02:12

+0

在许多情况下,编译器由于外部因素(如低端硬件)而无法优化。而且,当然,优化,无论简单与否,都必须实施,并且再次遵循假设规则,您可以**决定应用一些。如果你编写了一个编译器,那么常量折叠是你的第一个担忧? – edmz 2015-04-02 09:11:55