2015-04-02 55 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