Подобное функции макроопределение в C

Я хотел бы определить функцию как МАКРОС. т.е.

#define foo(x)\
#if x>32\
 x\
#else\
 (2*x)\
#endif

то есть,

if x>32, then foo(x) present x
else, foo(x) present (2*x)

но моя GCC жалуется на:

int a = foo(31);

Я думаю, что препроцессор C должен быть дескриптором это правильно. с тех пор во время компиляции, это знает x=33. это могло заменить foo(33) с (2*33)

7
задан Vanni Totaro 1 June 2016 в 22:47
поделиться

5 ответов

Рассмотрим:

int x = rand()
int y = foo( x );

x неизвестен во время компиляции.

3
ответ дан 6 December 2019 в 06:13
поделиться

Вы можете сделать следующее

#define foo(x) ((x) > 32 ? (x) : (2 * (x)))

Но это оценивает x несколько раз. Вместо этого вы можете создать статическую функцию, что чище

static int foo(int x) {
  if(x > 32) 
    return x;
  return 2 * x;
}

Тогда вы также сможете передавать в foo вещи, которые имеют побочные эффекты, и чтобы побочный эффект проявлялся только один раз.

То, что вы написали, использует директивы препроцессора #if, #else и #endif, но вам нужно использовать языковые конструкции, если вы передаете переменные в макрос и хотите оценить их значения. Использование операторов if и else как настоящих языковых конструкций также не работает, потому что операторы потока управления не оценивают значения. Другими словами, оператор if управляет только потоком управления ("если A, то выполнить B, иначе выполнить C"), не оценивая никаких значений.

13
ответ дан 6 December 2019 в 06:13
поделиться

Проблема не в теории: при условии, что вы по какой-то причине хотите иметь макрос, который расширяется по-разному в зависимости от значения переданного ему параметра, и этот параметр является константа, известная препроцессору макроса, нет причин, по которым она не может работать ... для универсального макропроцессора ... Но, к сожалению, cpp не допускает присутствие других "команд" макропроцессора в определении макроса ...

Таким образом, ваш

#define foo(x) \
#if x>32 \
  x      \
#else    \
  2*x    \
#endif

не расширяется до

#if X>32
  X
#else
  2*X
#endif

, где X - известный параметр (поэтому измените X на, например, 31), что требует еще одного прохода препроцессором.

Более того, новые строки игнорируются, хотя они важны для такого использования; в противном случае следующий трюк (который, однако, требует еще одного прохода предварительной обработки)

#define foo(x,y) \
y if x>32 \
  x  \
y else \ 
  2*x \
y endif

, который с foo (20, #) производит

# if 20>32 20 # else 2*20 # endif

, который будет работать, если он будет

# if 20>32
  20
# else
  2*20
# endif

... но это не так (и, как уже говорилось, выходные данные препроцессора должны быть снова переданы препроцессору ...)

Итак, я отвечаю, что если вам нужны эти вещи, вы не можете использовать препроцессор C. ; вам следует использовать необычный (не стандартный?) препроцессор C или просто другой макропроцессор, и если вам нужны вещи, которые "cpp" должен "интегрировать" с C, то вы не можете использовать общий препроцессор ( как M4) так легко ...

2
ответ дан 6 December 2019 в 06:13
поделиться
int a = foo(31);

Расширяется до

int a = if 31>32
31
else
(2*31)
endif;

Вот как работают макросы C с помощью простой и бессмысленной замены. Если вы ожидаете, что gcc сделает с ними что-то более сложное или умное, то ваше ожидание ошибочно.

Учитывая это, легко понять, почему ваш код не работает. Альтернативой, которая была бы достаточной для этого примера, была бы следующая:

#define foo(x) (x > 32 ? x : 2*x)

С другой стороны, я бы поставил под сомнение, действительно ли макросы являются подходящим инструментом для таких вещей с самого начала. Просто вставьте его в функцию, и компилятор встроит код, если посчитает, что это ускорит его.

3
ответ дан 6 December 2019 в 06:13
поделиться
#define \
    foo(x) \
    ({ \
        int xx = (x); \
        int result = (xx > 32) ? xx : (2*xx); \
        result; \
    })
8
ответ дан 6 December 2019 в 06:13
поделиться
Другие вопросы по тегам:

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