#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);