Стандарт C (насколько я знаю, во всех его версиях) позволяет любой стандартной функции библиотеки также быть определена как макрос. В текущем стандарте C, который скрыт в §7.1.4 (Использование библиотечных функций), абзац 1:
Любая функция, объявленная в заголовке, может быть дополнительно реализована как функционально-подобный макрос определено в заголовке… Любой вызов библиотечной функции, которая реализована в виде макроса, должен расширяться до кода, который оценивает каждый из своих аргументов ровно один раз, при необходимости он полностью защищен скобками, поэтому обычно безопасно использовать произвольные выражения в качестве аргументов.
Макросы могут быть определены стандартной реализацией библиотеки для обеспечения эффективности (хотя это менее важно, чем раньше, теперь, когда большинство компиляторов будут встроенными функциями), но функции также должны быть определенным как функции с точно такой же семантикой, что означает, что вы можете использовать функцию без включения заголовка (при условии, что вы предоставили правильный прототип функции) и что вы можете взять адрес функции.
И, как указано, я Во втором предложении, которое я цитировал, вам не нужно беспокоиться о возможных побочных эффектах макросов, таких как множественная оценка их аргументов - , если в описании функции не указано иное. (Одной из таких функций является getc
, которая семантически идентична fgetc
, за исключением того, что getc
разрешено реализовывать как макрос, который оценивает свой аргумент более одного раза.)
Это никогда не было так что эти функции были реализованы только как макросы (по крайней мере, не в стандартных библиотеках). Но было время, когда было так часто реализовывать простые функции, как макросы, что некоторые люди просто рассчитывали на существующие макросы. Или говорили о них, как будто это было единственное осуществление.
Ничего из этого не имеет место в C ++. C ++ требует, чтобы функции были функциями (а макросы - макросами), а функции находятся в пространствах имен. Это не делало C ++ несовместимым с C; это было просто необходимо для заголовков C ++, которые объявляют функции, совместно используемые с C (то есть теми, чьи имена начинаются с c
), до #undef
всех (потенциальных) определений макросов после включения соответствующего заголовка C.