Легко понять, как будет работать такой код:
#include <string.h>
#define strcmp my_strcmp
int my_strcmp(const char *, const char *)
...
strcmp(str1, str2);
...
Но этот вопрос заключается в том, является ли это технически правильным или нет.
Из C11:
7.1.3.1 (для зарезервированных имен):
...
- Каждое имя макроса в любом из следующих подпунктов (включая будущую библиотеку направления) зарезервировано для использования, как указано, если включен какой-либо из его связанных заголовков; если явно не указано иное (см. 7.1.4).
- Все идентификаторы с внешней связью в любом из следующих подпунктов (включая будущие направления библиотек) и errno всегда зарезервированы для использования в качестве идентификаторов с внешняя связь. 184)
- Каждый идентификатор с областью файлов, указанный в любом из следующих подпунктов (включая будущие направления библиотек) зарезервирован для использования в качестве имени макроса и в качестве идентификатора с область файла в том же пространстве имен, если включен какой-либо из связанных заголовков.
184 Список зарезервированных идентификаторов с внешней связью включает в себя math_errhandling, setjmp, va_copy и va_end.
Таким образом, это означает, что strcmp
является зарезервированным словом, потому что string.h
включен.
7.1.3.2:
... Если программа объявляет или определяет идентификатор в контексте, в котором он зарезервирован (кроме как разрешено в соответствии с 7.1.4), или определяет зарезервированный идентификатор в качестве имени макроса, поведение undefined.
Теперь это говорит о переопределении strcmp
поведения undefined, за исключением того, что это разрешено в 7.1.4.
Возможно, релевантное содержание 7.1.4:
7.1.4.1:
... Любая функция, объявленная в заголовке, может быть дополнительно реализована как функционально подобный макрос, определенный в заголовке, поэтому, если функция библиотеки объявлена явно при включении заголовка, можно использовать один из приведенных ниже методов чтобы макрос не влиял на декларацию. Любое макроопределение функции может быть подавлено локально путем включения имени функции в круглые скобки, потому что вместо этого имени не следует левая скобка, которая указывает на расширение имени функции макрофункции. По той же синтаксической причине разрешается брать адрес библиотечной функции, даже если он также определен как макрос. 185) Использование #undef для удаления любого определения макроса также гарантирует, что ссылается на фактическую функцию....
185 Это означает, что реализация должна предоставлять фактическую функцию для каждой библиотечной функции, даже если она также предоставляет макрос для этой функции.
7.1.4.2:
При условии, что функция библиотеки может быть объявлена без ссылки на любой тип, определенный в заголовке, также разрешено объявлять функцию и использовать ее без включения ее связанный заголовок.
Остальные пункты не имеют значения. Я не вижу, что 7.1.3.2 называется "разрешенным по 7.1.4", за исключением определения функции библиотеки в том же заголовке, что и функция, т.е. Стандартный заголовок, в качестве макроса.
В целом, это код выше techincally undefined поведения? Как насчет того, если string.h
не был включен?