2016-01-15 6 views
-2

Я попытался с помощью этого макроса:Macro неисправность результат операции

#define min(x,y) x<y? x:y 

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

Пример

x=min(3,4); 

Здесь х будет, естественно, 3 в качестве значения, но при попытке это:

x= 23 + min(3,4); 

результат все равно будет всегда 3 (результат макро), нет вопрос, какое число я добавляю к нему (23 был произвольным там). Могу ли я узнать, почему это происходит?

+0

Когда я пробую ваш код, результат равен 4, а не 3. – Barmar

+0

См. Http://ideone.com/alrhCf – Barmar

+1

УРОК: не используйте макросы, где вы должны использовать функции –

ответ

2

min должен быть определен как:

#define min(a,b) (((a) < (b)) ? (a) : (b)) 

Вы также, кажется, смешивания MIN и min. C чувствителен к регистру, поэтому min() может вызвать что-то другое.

#define min(X,Y) X<Y? X:Y // I changed MIN to lowercase here 
x= 23 + min(3,4); 

-> расширится:

x = 23 + 3 < 4 ? 3 : 4; 

который является таким же, как:

x = (23 + 3) < 4 ? 3 : 4; 

Вот почему необходимы круглые скобки:

x = 23 + ((3 < 4) ? 3 : 4); 

Чтобы избежать дальнейших проблем с: min(x | b + 4/2, y && 0x01 + 3);, круглые скобки добавляются вокруг всех значений:

(((a) < (b)) ? (a) : (b)) 

При использовании таких макросов, следует соблюдать осторожность при следующем:

int y = 1; 
int z = 2; 

x = min(y++, z++); 

Это имеет значение:

x = ((y++ < z++) ? y++ : z++); // some parentheses omitted 

Который не ват, мы хотим. y или z будет увеличиваться в два раза.

+0

мин работает просто отлично –

+0

@Jdoe - Я добавляю больше информации –

+0

, по сути, я использовал его как min not MIN, и я попробовал его с совершенно другим именем и все тем же. –

0

Это потому, что + имеет самый высокий приоритет, < следующий и? имеет самый низкий приоритет.Так,

23 + min(3,4) 

расширяется

23 + 3 < 4 ? 3 : 4 

Таким образом, добавление делается первым, и тогда вам придется:

26 < 4 ? 3 : 4 

Затем делается реляционная оператор, и вы» d имеют:

0 ? 3 : 4 

Итак, вы делаете В результате я получаю 4.

1

Это хороший пример того, почему важна скобка в макросах.

Это:

x= 23 + min(3,4); 

Расширяет к этому:

x= 23 + 3<4? 3:4; 

Который, с неявной скобкой, то же самое, как:

x= ((23 + 3)<4)? 3:4; 

Это имеет значение 4.

Если вы определяете свой макрос как это:

#define min(x,y) ((x)<(y)?(x):(y)) 

Тогда вы получите это:

x= 23 + ((3)<(4)?(3):(4)); 

Тройная оценивает 3, поэтому х назначается 26.

+0

О, мой! большое спасибо!!! –

2

Проблема является оператором assocativity и старшинство. Когда вы расширяете макрос, он становится:

x = 23 + 3 < 4 ? 3 : 4; 

, который интерпретируется как:

x = (23 + 3) < 4 ? 3 : 4; 

, потому что арифметика имеет более высокий приоритет, чем операторы сравнения. Вы должны заключить расширение в круглые скобки, чтобы заставить его рассматриваться как одно выражение.

#define min(x,y) (x<y? x:y) 

Вы также должны положить Parenthese вокруг использования каждого параметра, в случае, если они выражения с операторами, которые имеют более низкий приоритет, чем <.

#define min(x,y) ((x) < (y) ? (x) : (y)) 

DEMO

Но используя макрос для функции, как это по-прежнему плохая идея. Все повторения параметров означают, что вы не можете использовать его с выражениями с побочными эффектами. Например. min(i++, j++) будет увеличивать одну из переменных дважды. Было бы лучше использовать встроенную функцию.