Препроцессорное постоянное складывание - PullRequest
0 голосов
/ 29 июня 2018

У меня есть фундаментальный вопрос относительно оценки константы препроцессора C, и я хотел бы получить некоторую помощь в понимании того, поможет ли препроцессор оптимизировать код в такой ситуации. Я понимаю, что препроцессор просто «заменяет текст» в коде. По этому правилу даже константные выражения заменяются в коде. Например, следующий код:

#include <stdio.h>

#define MY_NUM 2+2*2

int main()
{
    int a = 6/MY_NUM;
    printf("a: %d\n", a);
    return 0;
}

Значение a равно 7. Это потому, что предварительно обработанный код выглядит примерно так:

int main()
{
    int a = 6/2+2*2;
    printf("a: %d\n", a);
    return 0;
}

Я вижу, что MY_NUM не оценивалось до 6, прежде чем начнется компиляция. Конечно, компилятор затем оптимизирует код, оценивая значение a во время компиляции.

Я не уверен, происходит ли постоянное свертывание препроцессора или нет, или это вообще возможно. Или есть какой-либо способ (флаг в GCC), чтобы включить его. Обычные -O оптимизации не позволяют это сделать. Можно ли как-нибудь изменить здесь поведение препроцессора?

Я использую gcc 4.8.4 для моего кода.

Ответы [ 2 ]

0 голосов
/ 29 июня 2018

Препроцессор имеет собственный калькулятор константных значений, он использует этот калькулятор для получения значений выражений во всех условных операторах #if # elif.

Даже если можно свернуть константы из списков замены токенов препроцессора, он никогда этого не сделает, просто потому, что не может знать, обрабатывает ли он код C или какой-либо другой текст / язык.

Препроцессор C имеет универсальное применение, он не предназначен только для предварительной обработки языка C.

Компилятор C может иметь свое собственное постоянное сворачивание внутри синтаксического анализатора, который анализирует токены C.

0 голосов
/ 29 июня 2018

Нет, единственный раз, когда препроцессор оценивает любое выражение, находится в #if / #elif.

Вы можете подделать арифметику, применив ее в терминах конкатенации токенов и тонны макросов, но это гораздо сложнее, чем просто

#define MY_NUM (2+2*2)

Но простого переключателя компилятора не существует, потому что расширение макроса - это просто замена токена.

...