C - параметризованные макросы - PullRequest
4 голосов
/ 15 марта 2012

Я могу выяснить, в чем преимущество использования

#define CRANDOM() (random() / 2.33);

вместо

 float CRANDOM() {
    return random() / 2.33;
}

Ответы [ 5 ]

5 голосов
/ 15 марта 2012

Используя #define macro, вы принудительно вставляете тело макроса inline .

При использовании функции 1 будет функциейвызов (и, следовательно, переход к адресу функции (среди прочего)), что несколько замедлит производительность.

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



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

3 голосов
/ 15 марта 2012

Во-первых, это #define неверно из-за точки с запятой в конце, и компилятор будет ошибаться при:

float f = CRANDOM() * 2;

Во-вторых, я лично стараюсь избегать использования препроцессора, кроме разделения независящих от платформы разделов в кроссплатформенном коде и, конечно, кода, зарезервированного исключительно для сборок DEBUG или не-DEBUG.

Nightcracker правильно заявляет, что он всегда будет «эффективно» встроенным, но, учитывая, что вы можете переписать функцию так, чтобы она была inline, я не вижу никакого преимущества в использовании версии препроцессора , если C- рассматриваемый компилятор не встроен.

3 голосов
/ 15 марта 2012

Он гарантирует, что вызов CRANDOM является встроенным, даже если компилятор не поддерживает встраивание.

1 голос
/ 15 марта 2012

Бывший старый стиль.Единственное преимущество первого состоит в том, что если у вас есть компилятор, соответствующий старому стандарту C90, макрос будет работать как встроенный.В современном компиляторе C вы всегда должны писать:

inline float CRANDOM() {
    return random() / 2.33f;
}

, где ключевое слово inline является необязательным.


(обратите внимание, что литералы с плавающей точкой должны иметь af в конце, в противном случае вы заставляетевычисление, которое будет выполнено для двойного числа, которое вы затем неявно округляете в число с плавающей точкой.)

0 голосов
/ 15 марта 2012

Вызов функции влечет за собой небольшие накладные расходы - в этом случае добавление адреса возврата в стек машины и ветвление. Используя макрос, вы можете избежать этих издержек. Давным-давно это было важно; в наши дни многие компиляторы вставляют тело крошечной функции, такой как эта, в любом случае. В общем, попытка обмануть компилятор в создании более быстрого кода - игра для дурака; вы часто заканчиваете тем, что создаете что-то медленнее.

...