Подтвердить что ты не робот

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

Как говорится в этом вопросе, препроцессор C способен сделать это?

например:.

#define PI 3.1416
#define OP PI/100
#define OP2 PI%100

Можно ли рассчитывать OP и/или OP2 на этапе предварительной обработки?

4b9b3361

Ответ 1

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

#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); (плюс, вероятно, некоторые вещи, указывающие имена файлов и номера строк и т.д.).

Ответ 2

Код, который вы написали, фактически не делает препроцессор выполненным. #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

Ответ 3

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

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

Ответ 4

Да, это можно сделать с помощью препроцессора Boost. И он совместим с чистым C, поэтому вы можете использовать его в программах на C только с компиляциями C. Ваш код включает числа с плавающей запятой, поэтому я думаю, что это нужно сделать косвенно.

#include <boost/preprocessor/arithmetic/div.hpp>
BOOST_PP_DIV(11, 5) // expands to 2
#define KB 1024
#define HKB BOOST_PP_DIV(A,2)
#define REM(A,B) BOOST_PP_SUB(A, BOOST_PP_MUL(B, BOOST_PP_DIV(A,B)))
#define RKB REM(KB,2)

int div = HKB;
int rem = RKB;

Это предварительная обработка (проверка с помощью gcc -S)

int div = 512;
int rem = 0;

Благодаря этой теме.

Ответ 5

Да.

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

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

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

Ответ 6

Будьте осторожны при выполнении арифметики: добавьте скобки.

#define SIZE4 4
#define SIZE8 8
#define TOTALSIZE SIZE4 + SIZE8

Если вы когда-нибудь используете что-то вроде:

unsigned int i = TOTALSIZE/4;

и ожидайте, что я буду 3, вы получите 4 + 2 = 6 вместо этого. Добавить скобку:

#define TOTALSIZE (SIZE4 + SIZE8)