Как я слышал, я мог бы ускорить еще больше, поставив эту функцию в пункте #define
Я думаю, вы, должно быть, неправильно поняли. Разумеется, совет заключался в том, чтобы реализовать поведение как a (#define
d) макрос, вместо как функция. Ваш макрос синтаксически действителен, но код, полученный при его расширении, не является подходящей заменой для вызова вашей функции.
Определение этого как макроса в основном является способом ручного ввода тела функции, но имеет некоторые недостатки. В частности, в стандарте C макрос, который должен быть расширен до выражения (то есть тот, который может использоваться как значение), не может содержать кодовый блок и, следовательно, не может содержать объявления переменных. Это, в свою очередь, может сделать невозможным избежать многократной оценки аргументов макроса, что является большой проблемой.
Вот один способ, которым Вы могли бы написать макрос:
#define mfmod(x,y) (((x)/(y)) - (int) ((x)/(y)))
Это не ясно, победа над функцией, однако, так как его поведение зависит от типов аргументов, он должен оценить оба аргумента дважды (что может привести к неожиданным и даже неопределенным результатам в некоторых случаях), и он должен также выполнять разделение дважды.
Если вы были готовы изменить режим использования, чтобы макрос задавал переменную результата вместо того, чтобы расширять ее до выражения, тогда вы можете обойти многие проблемы. @BnBDim предоставил первый разрез в этом, но он страдает от некоторых из тех же типов и проблем с множественной оценкой, что и выше.Вот как вы можете сделать это, чтобы получить тот же результат, что ваша функция:
#define mfmod(x, y, res) do { \
double _div = (y); \
double _quot = (double) (x)/_div; \
res = (_quot - (int) _quot) * _div; \
} while (0)
Обратите внимание, что он берет на себя, чтобы ссылаться на аргументы один раз, а также в скобках, но и для res
, который должен быть именующее. Вы могли бы использовать его так же, как пустую функцию, а не как стоимость возвращения функции:
double test;
mfmod(f, div, test);
Это все еще позволяет себе незначительный, но неизбежный риск поломки в том случае, если один из фактических аргументов макрос сталкивается с одна из переменных, объявленных внутри блока кода, который она предоставляет. Использование имен переменных с префиксом подчеркивания предназначено для минимизации этого риска.
В целом, я был бы склонен идти с функцией вместо этого и позволить компилятору обрабатывать вставку. Если вы хотите, чтобы это побудило компилятор, вы можете рассмотреть возможность объявления функции inline
, но, скорее всего, он не понадобится такой намек, и он не обязан отмечать его.
Или лучше, просто используйте fmod()
до тех пор, пока вы не определите, что это является узким местом.
За исключением вопроса о последовательности (вы не знаете, будет ли задание выполнено до того, как значение 'a' будет считано для вычитания) и что переменная' a' не будет доступна за пределами области блока , и что он вернется из любой функции, в которой он находится (что может и не быть проблемой), ваш макрос выглядит нормально. Вы должны дать нам нечто большее, чем «дает проблемы». Пожалуйста, [прочитайте о том, как задавать хорошие вопросы] (http://stackoverflow.com/help/how-to-ask) и узнайте, как создать [Минимальный, полный и проверенный пример] (http://stackoverflow.com/помощь/mcve). –
Обратите внимание, что 'x' &' y' могут быть выражениями, и вам придется их скопировать, чтобы избежать побочных эффектов. –
@Someprogrammerdude нет у него есть 'return' –