#define используется с операторами

Я знаю это #define имеет следующий синтаксис: #define SYMBOL stringЕсли я напишу, например

#define ALPHA 2-1
#define BETA ALPHA*2

затем ALPHA = 1 но BETA = 0.(Зачем?)

Но если я напишу что-то вроде этого

#define ALPHA (2-1)
#define BETA ALPHA*2

затем ALPHA = 1 а также BETA = 2,

Может кто-нибудь объяснить мне, в чем разница между этими двумя?

4 ответа

Решение

Макросы препроцессора, созданные с использованием #define текстовые замены.

Два примера не эквивалентны. Первые наборы BETA в 2-1*2, Вторые сеты BETA в (2-1)*2, Неправильно утверждать, что ALPHA == 1 как ты, потому что ALPHAэто не число - это свободный человек! это просто последовательность символов.

При разборе на C или C++ эти два выражения различаются (первое совпадает с 2 - (1*2)).

Мы можем показать разницу, распечатав строку расширения BETA а также оценивая это как выражение:

#ifdef PARENS
#define ALPHA (2-1)
#else
#define ALPHA 2-1
#endif

#define BETA ALPHA*2

#define str(x) str2(x)
#define str2(x) #x

#include <stdio.h>
int main()
{
    printf("%s = %d\n", str(BETA), BETA);
    return 0;
}

Скомпилируйте выше с и без PARENS определяется, чтобы увидеть разницу:

(2-1)*2 = 2
2-1*2 = 0

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

#define ALPHA (2-1)
#define BETA ((ALPHA)*2)

Макро (#define ...) только текстовая замена.

С этой версией:

#define ALPHA 2-1
#define BETA ALPHA*2

Препроцессор заменить BETA от ALPHA*2 затем заменить ALPHA от 2-1, Когда расширение макроса закончено, BETA заменяется 2-1*2 который (из-за приоритета оператора) равен 2-(1*2)=0

Когда вы добавляете круглые скобки вокруг "значенияALPHA" (ALPHA на самом деле не имеет значения, так как макрос - это просто замена текста), вы меняете порядок оценки операции. Сейчас BETA заменяется (2-1)*2 который равен 2.

Порядок операций. Первым примером становится 2-1*2, что равно 2-2. Второй пример, с другой стороны, расширяется до (2-1)*2, что оценивается как 1*2.

В первом примере:

#define ALPHA 2-1
#define BETA ALPHA*2

альфа заменяется на любое значение, которое вы ей дали (в данном случае 2-1). Это приводит к расширению BETA до (становится) 2-1*2, что оценивается в 0, как описано выше.

Во втором примере:

#define ALPHA (2-1)
#define BETA ALPHA*2

Альфа (в пределах определения BETA) расширяется до значения, для которого она была установлена ​​(2-1), что приводит к расширению BETA до (2-1) * 2 при каждом его использовании.

В случае, если у вас возникли проблемы с порядком операций, вы всегда можете использовать аббревиатуру PEMDAS, чтобы помочь вам (вычитание сложения с умножением экспоненциального умножения), которое можно вспомнить как "Пожалуйста, извините мою дорогую тетю Салли". Первые операции в аббревиатуре всегда должны выполняться перед более поздними операциями в аббревиатуре (за исключением умножения и деления (в которых вы просто идете слева направо в уравнении, поскольку считается, что они имеют равный приоритет, а сложение и вычитание (тот же сценарий, что и умножение и деление).

Макросы в c/ C++ - это просто текстовые замены, а не функции. Таким образом, макрос предназначен для того, чтобы просто заменить имя макроса в тексте программы его содержимым, прежде чем событие компилятора попытается проанализировать код. Так что в первом случае компилятор увидит это:

BETA ==> ALPHA * 2 ==> 2 - 1 * 2 ==> compiler ==> 0
printf("beta=%d\n", BETA); ==> printf("beta=%d\n", 2 - 1 * 2);

Во-вторых

BETA ==> ALPHA * 2 ==> (2 - 1) * 2 ==> compiler ==> 2
printf("beta=%d\n", BETA); ==> printf("beta=%d\n", (2 - 1) * 2);
Другие вопросы по тегам