Встроенные функции против макросов препроцессора

Как встроенная функция отличается от макроса препроцессора?

Ответ 1

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

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

Теперь, что касается использования макросов и встроенных функций в функционально-подобном контексте, имейте в виду, что:

  • Макросы не являются безопасными по типу и могут быть расширены независимо от того, являются ли они синтаксически правильными - на этапе компиляции будут сообщаться о ошибках, возникающих в результате проблем с макрообъемением.
  • Макросы могут использоваться в контексте, где вы не ожидаете, что приводит к проблемам
  • Макросы более гибкие, поскольку они могут расширять другие макросы, тогда как встроенные функции не обязательно делают это.
  • Макросы могут вызывать побочные эффекты из-за их расширения, поскольку входные выражения копируются везде, где они появляются в шаблоне.
  • Не всегда гарантируется встроенная функция - некоторые компиляторы делают это только в сборках релизов или когда они специально настроены для этого. Кроме того, в некоторых случаях встраивание может быть невозможно.
  • Встроенные функции могут обеспечивать область переменных (в частности, статических), макросы препроцессора могут делать это только в блоках кода {...}, а статические переменные не будут вести себя точно так же.

Ответ 2

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

Например, если вы хотите сравнить 2 значения:

#define max(a,b) ((a<b)?b:a)

Побочные эффекты появляются, если вы используете max(a++,b++), например (a или b будет увеличиваться дважды). Вместо этого используйте (например)

inline int max( int a, int b) { return ((a<b)?b:a); }

Ответ 3

Функция Inline расширяется компилятором, где по мере того, как макросы расширяются препроцессором, который представляет собой просто текстовую замену. Хенд

  • Во время вызова макроса не проверяется тип, в то время как проверка типов выполняется во время вызова функции.

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

    #define MAX(a,b) ((a)>(b) ? (a) : (b))
    int i = 5, j = MAX(i++, 0);
    

    приведет к

    int i = 5, j = ((i++)>(0) ? (i++) : (0));
    
  • Макро-аргументы не вычисляются до расширения макроса

    #define MUL(a, b) a*b
    int main()
    {
      // The macro is expended as 2 + 3 * 3 + 5, not as 5*8
      printf("%d", MUL(2+3, 3+5));
     return 0;
    }
    // Output: 16`
    
  • Ключевое слово return не может использоваться в макросах для возврата значений, как в случае с функциями.

  • Встроенные функции могут быть перегружены

  • Токены, переданные в макросы, могут быть объединены с помощью оператора ##, называемого оператором Token-Pasting.

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

Ответ 4

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

Здесь указаны несколько других менее очевидных точек.

Ответ 5

Чтобы добавить еще одно отличие от уже заданных: вы не можете пройти через #define в отладчике, но можете выполнить встроенную функцию.

Ответ 6

Макросы игнорируют пространства имен. И это делает их злыми.

Ответ 7

встроенные функции похожи на макросы (поскольку код функции расширяется в точке вызова во время компиляции), встроенные функции анализируются компилятором, тогда как макросы расширяются препроцессором. В результате есть несколько важных отличий:

  • Встроенные функции соответствуют всем протоколам безопасности типов, которые применяются в нормальных функциях.
  • Встроенные функции задаются с использованием того же синтаксиса, что и любая другая функция, за исключением того, что они включают ключевое слово inline в объявлении функции.
  • Выражения, переданные как аргументы встроенным функциям, оцениваются один раз.
  • В некоторых случаях выражения, переданные в качестве аргументов для макросов, могут быть оценены более одного раза. http://msdn.microsoft.com/en-us/library/bf6bf4cf.aspx

    Макросы
  • расширяются за время компиляции, вы не можете использовать их для отладки, но вы можете использовать встроенные функции.

- хорошая статья: http://www.codeguru.com/forum/showpost.php?p=1093923&postcount=1

;

Ответ 8

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

Ответ 9

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

Ответ 10

В GCC (я не уверен в других), объявляя функцию inline, это всего лишь подсказка для компилятора. В конце дня все еще зависит от компилятора, чтобы решить, включает ли он тело функции всякий раз, когда он вызывается.

Разница между встроенными функциями и макросами препроцессора относительно велика. Макросы препроцессора - это просто замена текста в конце дня. Вы отказываетесь от способности компилятора выполнять проверку проверки типов на аргументы и тип возвращаемого значения. Оценка аргументов сильно отличается (если выражения, которые вы передаете в функции, имеют побочные эффекты, вы будете очень весело отлаживать время). Существуют тонкие различия в том, где можно использовать функции и макросы. Например, если бы у меня было:

#define MACRO_FUNC(X) ...

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

if(MACRO_FUNC(y)) {
 ...body
}

Нормальная функция может быть использована без проблем.

Ответ 11

С точки зрения кодирования встроенная функция подобна функции. Таким образом, различия между встроенной функцией и макросом совпадают с различиями между функцией и макросом.

С точки зрения компиляции встроенная функция похожа на макрос. Он вводится непосредственно в код, не вызываемый.

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

Ответ 12

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

Ответ 13

Inline или Macro, который увеличит размер кода?

Ответ 14

#include<iostream>
using namespace std;
#define NUMBER 10 //macros are preprocessed while functions are not.
int number()
{ 
    return 10;
}
/*In macros, no type checking(incompatible operand, etc.) is done and thus use of micros can lead to errors/side-effects in some cases. 
However, this is not the case with functions.
Also, macros do not check for compilation error (if any). Consider:- */
#define CUBE(b) b*b*b
int cube(int a)
{
 return a*a*a;
}
int main()
{
 cout<<NUMBER<<endl<<number()<<endl;
 cout<<CUBE(1+3); //Unexpected output 10
 cout<<endl<<cube(1+3);// As expected 64
 return 0;
}

Макросы, как правило, быстрее, чем функции, поскольку они не связаны с накладными расходами на функциональные вызовы.

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

Макросы обычно представляют собой один вкладыш. Однако они могут состоять из нескольких строк. В функциях нет таких ограничений.