Препроцессор C может выполнить целочисленную арифметику?

Другая альтернатива, которая применима в некоторых случаях, является полиморфизмом времени компиляции с шаблонами. Полезно, например, когда Вы хотите сделать выбор реализации в начале программы, и затем использовать ее на время выполнения. Пример с полиморфизмом во время выполнения

class AbstractAlgo
{
    virtual int func();
};

class Algo1 : public AbstractAlgo
{
    virtual int func();
};

class Algo2 : public AbstractAlgo
{
    virtual int func();
};

void compute(AbstractAlgo* algo)
{
      // Use algo many times, paying virtual function cost each time

}   

int main()
{
    int which;
     AbstractAlgo* algo;

    // read which from config file
    if (which == 1)
       algo = new Algo1();
    else
       algo = new Algo2();
    compute(algo);
}

тот же полиморфизм времени компиляции использования

class Algo1
{
    int func();
};

class Algo2
{
    int func();
};


template<class ALGO>  void compute()
{
    ALGO algo;
      // Use algo many times.  No virtual function cost, and func() may be inlined.
}   

int main()
{
    int which;
    // read which from config file
    if (which == 1)
       compute<Algo1>();
    else
       compute<Algo2>();
}
22
задан Brian Tompsett - 汤莱恩 13 February 2016 в 21:39
поделиться

4 ответа

Целочисленная арифметика? Запустите следующую программу, чтобы узнать:

#include "stdio.h"
int main() {
    #if 1 + 1 == 2
        printf("1+1==2\n");
    #endif
    #if 1 + 1 == 3
        printf("1+1==3\n");
    #endif
 }

Ответ - «да», есть способ заставить препроцессор выполнять целочисленную арифметику, то есть использовать ее в условии препроцессора.

Обратите внимание, однако, что ваши примеры не являются целочисленной арифметикой. Я только что проверил, и препроцессор gcc не работает, если вы попытаетесь заставить его выполнять сравнения с плавающей запятой. Я не проверял, разрешает ли стандарт когда-либо арифметику с плавающей запятой в препроцессоре.

Обычное расширение макроса не оценивает целочисленные выражения, оно оставляет его компилятору, как можно увидеть, предварительно обработав (-E в gcc) следующие :

#define ONEPLUSONE (1 + 1)
#if ONEPLUSONE == 2
    int i = ONEPLUSONE;
#endif

Результат: int i = (1 + 1); (плюс, вероятно, некоторые вещи для указания имен исходных файлов, номеров строк и т. Д.).

30
ответ дан 29 November 2019 в 03:38
поделиться

Написанный вами код на самом деле не заставляет препроцессор производить какие-либо вычисления. #Define выполняет простую замену текста, поэтому определено следующее:

#define PI 3.1416
#define OP PI/100

Этот код:

if (OP == x) { ... }

становится

if (3.1416/100 == x) { ... }

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

if (0.031416 == x) { ... }

Но это компилятор, а не препроцессор.

Чтобы ответить на ваш вопрос, да, препроцессор МОЖЕТ делать некоторые арифметические операции. Это можно увидеть, если вы напишете что-то вроде этого:

#if (3.141/100 == 20)
   printf("yo");
#elif (3+3 == 6)
   printf("hey");
#endif
19
ответ дан 29 November 2019 в 03:38
поделиться

ДА , я имею в виду: он может выполнять арифметические операции :)

Как показано в 99 бутылок пива .

7
ответ дан 29 November 2019 в 03:38
поделиться

Да.

Я не могу поверить, что нет еще один связан с определенным победителем конкурса C. Этот парень реализовал ALU в препроцессоре с помощью рекурсивных включений. Здесь - реализация, а здесь - что-то вроде объяснения.

Теперь, при этом, вы не хотите делать то, что сделал этот парень. Это весело и все такое, но посмотрите на время компиляции в его файле подсказок (не говоря уже о том, что получившийся код невозможно поддерживать). Чаще люди используют препроцессор строго для замены текста, а вычисление арифметических операций с постоянными целыми числами происходит либо во время компиляции, либо во время выполнения.

Однако, как отмечали другие, вы можете выполнять некоторые арифметические действия в операторах #if.

4
ответ дан 29 November 2019 в 03:38
поделиться
Другие вопросы по тегам:

Похожие вопросы: