Использование макроса для небольшой операции, это хорошая практика? - PullRequest
3 голосов
/ 08 января 2012

У меня есть небольшой фрагмент кода, который требует чтения 4-битных значений, упакованных в 32-битное целое число.Поскольку мне нужно вызывать эту операцию несколько раз, даже если она проста, мне требуется максимальная скорость.Я размышлял о макросах и встроенных функциях, поэтому я сделал этот макрос:

#define UI32TO4(x, p) (x >> ((p - 1) *4) & 15)

И у меня есть встроенная функция, которая делает то же самое.

static inline Uint8 foo_getval(Uint32 bits, int pos){
    return (bits >> ((pos-1)*4)) & 15;
}

Учитывая простотуоперации, и что значения уже подготовлены для этого вызова (поэтому нет возможности вызова неправильных типов или передачи значений, которые слишком велики или тому подобное), что было бы лучше всего использовать?Или, по крайней мере, наиболее приемлемым для кого-то, кто потенциально читает / изменяет код позже?

РЕДАКТИРОВАТЬ!Забыл упомянуть, я использую C99.

Ответы [ 3 ]

8 голосов
/ 08 января 2012

Функция безопаснее.Ваши предположения о том, что значения всегда «правильные», верны только во время разработки этого кода.Вы не можете сказать, не пропустит ли кто-нибудь из себя (или вам самим, когда вы устали) неожиданные значения.

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

4 голосов
/ 08 января 2012

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

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

Кроме того, функция предупреждает вас о типах параметров и не позволяет дать двойное число для pos.Макрос может позволить это.

2 голосов
/ 08 января 2012

Уже поздно, и я раздражительный (и, вероятно, я постараюсь удалить этот пост позже), но я устаю слышать одни и те же аргументы против макросов, попугаев снова и снова (двойная избыточность):

  • Йоахим Пилеборг (выше) утверждает, что «использование функции позволяет компилятору лучше проверять типы». Это часто говорят , но я не верю этому. С макросами компилятор уже имеет в своем распоряжении all доступную информацию о типе. Функции просто разрушают это. (И, возможно, уничтожить оптимизацию, выдвинув регистры в стек, но это побочная проблема.)

  • И frast (выше) заявляет, что «макросы могут вызывать нежелательные побочные эффекты». Правда - но так что может функционировать Я думаю, что правило - всегда использовать UPPER_CASE для макросов , которые не имеют семантику функций. Это правило часто нарушалось. Но это не применимо здесь: OP избыточно использовал семантику функций и в верхнем регистре и .

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

   #define UI32TO4(x, p) ((x) >> (((p) - 1) * 4) & 15)

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

Макросы, конечно, опасны, но также и функции. (И чем меньше сказано о STL,, тем лучше).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...