32bit_me (32bit_me) wrote,
32bit_me
32bit_me

Category:

Почему макросы - зло

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

Почему результат этого выражения = 3, а не 9 ?
Предположим, что в программе определён макрос sqr.


#define sqr(x) x*x



Какое значение будет иметь следующее выражение:


sqr(3+0)



Довольно очевидно, что результат будет 3 + 0 * 3 + 0 = 3, и это лишь первая ловушка, подстерегающая юных падаванов.

На самом деле,

#define sqr(x) x*x


- это образец того, как не нужно писать макросы.

Более правильно так:


#define SQR(x) ((x)*(x))



Тогда:

((3+0)*(3+0)) = 9



На этом всё, скажете вы? Заключить в круглые скобки каждый аргумент макроса и всё выражение подстановки, и дело в шляпе, всего-то? Невелика премудрость.

Однако, мои юные падаваны, тут царит темная сторона Силы...Это Зла обитель.

напишем такой пример:
#include <stdio.h>

#define SQR(x) ((x)*(x))

int main()
{
    int x = 4;
    int incX()
    {
        x++;
        return x;
    }
    printf("%d\n", SQR(incX()));

    return 0;
}


И вместо (казалось бы) ожидаемого SQR(5) = 25 получаем ВНЕЗАПНО 30.

Почему? Макрос развернул выражение как ((incX())*(incX())), и получилось 5 * 6 = 30, т.е. ф-ция incX() была вызвана два раза вместо ожидаемого одного.

Теперь верный вариант:

#include <stdio.h>

#define SQR(x) ({__auto_type _x=(x);_x*_x;})

int main()
{
    int x = 4;
    int incX()
    {
        x++;
        return x;
    }
    printf("%d\n", SQR(incX()));

    return 0;
}



И верный результат: 25.

Да пребудет с вами Сила!
Tags: #define, #include, C и C++, программирование
Subscribe

  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your reply will be screened

    Your IP address will be recorded 

  • 34 comments