#c #macros #inline
#c #макросы #встроенный
Вопрос:
Я не понимаю, в чем причина того, что макросы не оценивают свой аргумент только один раз (например, встроенные функции), но каждый раз, когда он используется в коде.
Например:
(пример взят отсюда: https://docs.microsoft.com/en-us/cpp/cpp/inline-functions-cpp?view=msvc-170 )
В этом коде есть макрос:
// inline_functions_macro.c
#include <stdio.h>
#include <conio.h>
#define toupper(a) ((a) >= 'a' amp;amp; ((a) <= 'z') ? ((a)-('a'-'A')):(a))
int main() {
char ch;
printf_s("Enter a character: ");
ch = toupper( getc(stdin) );
printf_s( "%c", ch );
}
// Sample Input: xyz
// Sample Output: Z
По сравнению с этим кодом с эквивалентной встроенной функцией:
// inline_functions_inline.cpp
#include <stdio.h>
#include <conio.h>
inline char toupper( char a ) {
return ((a >= 'a' amp;amp; a <= 'z') ? a-('a'-'A') : a );
}
int main() {
printf_s("Enter a character: ");
char ch = toupper( getc(stdin) );
printf_s( "%c", ch );
}
Комментарии:
1. Макросы представляют собой текстовые замены. Они не являются функциями.
2. Макросы не являются функциями. Это замена текста в препроцессоре, вот и все. Ни больше, ни меньше. Похоже, что ваш исходный код буквально содержит замененный текст, выполненный препроцессором, поэтому компилятор жалуется на использование каждого макроса, а не самого макроса.
3. Важно понимать, что макросы расширяются перед компиляцией, в том, что обычно называют «фазой предварительной обработки».
4. Попробуйте развернуть макрос со следующими аргументами: «hello» и 3.1415269. Это должно показать вам, почему функции предпочтительнее макросов.
Ответ №1:
Макросы не очень умны. Они просто выполняют подстановку текста перед началом компиляции.
Код:
#define toupper(a) ((a) >= 'a' amp;amp; ((a) <= 'z') ? ((a)-('a'-'A')):(a))
int main() {
char ch = toupper( getc(stdin) );
}
Инструктирует препроцессор изменить этот код и вместо этого передать его компилятору:
int main() {
char ch = ((getc(stdin)) >= 'a' amp;amp; ((getc(stdin)) <= 'z') ? ((getc(stdin))-('a'-'A')):(getc(stdin)));
}
Вы можете заметить, что toupper
это было заменено определенным выражением, в то время как каждое вхождение a
заменяется любым текстом, который был передан в качестве параметра макроса. Это не значение или выражение — это просто текст.
Помимо проблем, которые вы наблюдаете, вы также можете обнаружить, что ошибки компилятора будут показывать этот замененный код. Код, которого вы не видите в исходном файле.