2015-04-02 4 views
3

Я пытаюсь понять, как побитовые операции обрабатываются компиляторами C/C++. В частности, я говорю о C, скомпилированном с gcc, но я считаю, что вопрос немного более общий, чем этот.Побитовые операции компиляции в 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

+4

Это называется «постоянная складка», и вы можете быть уверены, что любой современный компилятор сделает это во время компиляции. – Sneftel

+0

вы, вероятно, захотите прочитать §6.6 («Константные выражения») в ИСО/МЭК 9899: 1999, в котором рассматривается это. Или, альтернативно, [этот обзор] (http://en.cppreference.com/w/c/language/constant_expression). –

ответ

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 оценить some_value во время компиляции

Я не знаю о вашей, шахта делает

Как проверить, поддерживает ли GCC такую ​​оптимизацию?

Я использовал флаг -s для генерации кода сборки и проверил его

movl $4, %esi 
+0

Проверьте ответ от simurg. Ваш компилятор не оптимизирует. Это предварительный процессор. Также я не думаю, что op хотел начать опрос по этому вопросу. – Matthias

5

Ваш компилятор не знает о себе SOME_VALUE. Код C сначала передается через C-препроцессор в компилятор C. Вы можете увидеть выход C препроцессор, запустив GCC как:

gcc -E code.c

Вы увидите, что реальный код подается на C компилятор:

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

Поэтому возникает вопрос «Есть ли C Компилятор GCC оптимизирует ((0x111UL) << (2)) & (7) ", и ответ да (как указывают другие ответчики, которые доказали это, посмотрев на сгенерированный код сборки).

+0

Спасибо! Я уже принял другой ответ, но ваш в равной степени полезен :) – kliteyn

-2

Как и другие, да, это будет. Но следует учитывать, что не требуется to; если вы хотите убедиться в этом, просто предварительно вычислите его, поскольку у вас есть все элементы для этого.

+0

Любые мотивы для голосования по голосу? – edmz

+0

Компилятор не * требуется * для оптимизации, конечно, но * почему бы не выбрать, если это не указано ('-O0')? Принимая во внимание, что постоянная сгибание является одной из основных доступных возможностей оптимизации? –

+0

Существует множество случаев, когда компилятор просто не может оптимизировать из-за внешних факторов (таких как низкокачественное оборудование). И, конечно же, оптимизация, простая или нет, должна быть реализована и, опять же, следуя правилу as-if, вы ** можете ** принять решение о применении некоторых. Если бы вы написали компилятор, будет ли ваша первая проблема постоянной сгибанием? – edmz

Смежные вопросы