Подводные камни define’ов

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

#define square1( a, b ) \
                a*= a; \
                b*= b;

И этот макрос работает в большинстве случаев корректно, но есть и исключения.

Например, если мы будем использовать это макрос как действие выполняемое по условию:

if( a > b ) square1( a, b );

В этом случае переменная b будет всегда возводиться в квадрат.
Что бы этого избежать, лучше пользоваться правилом: «многострочные define заключать в фигурные скобки».
Вот так:

#define square1( a, b ) \
             {         \
                a*= a; \
                b*= b; \
             }

Рассмотрим второй пример:

#define square2( a )   a*a

Такой макрос так же может служить источником ошибок:

 a = 1;
 b = 2;
 c = square2( a + b );

В результате переменная с будет равна 5 а не 9;

Вот вариант макроса который исключает возможность появления таких ошибок:

#define square2( a )    (a)*(a)

Можно сформулировать правило №2: «заключать в круглые скобки аргументы макроса если они используются как rvalue«

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

Добавить комментарий

Ваш e-mail не будет опубликован.

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>