It's easy to reason how such a code would work:
#include <string.h>
#define strcmp my_strcmp
int my_strcmp(const char *, const char *)
...
strcmp(str1, str2);
...
But this question is whether this is technically correct or not.
From C11:
7.1.3.1 (on reserved names):
...
- Each macro name in any of the following subclauses (including the future library
directions) is reserved for use as specified if any of its associated headers is included;
unless explicitly stated otherwise (see 7.1.4).
- All identifiers with external linkage in any of the following subclauses (including the
future library directions) and errno are always reserved for use as identifiers with
external linkage.184)
- Each identifier with file scope listed in any of the following subclauses (including the
future library directions) is reserved for use as a macro name and as an identifier with
file scope in the same name space if any of its associated headers is included.
184 The list of reserved identifiers with external linkage includes math_errhandling, setjmp, va_copy, and va_end.
So this means that strcmp
is a reserved word because string.h
is included.
7.1.3.2:
... If the program declares or defines an identifier in a context in which it is reserved (other than as allowed by 7.1.4), or defines a reserved identifier as a macro name, the behavior is undefined.
Now this seems to say redefining strcmp
is undefined behavior, except it is somehow allowed in 7.1.4.
The possibly relevant contents of 7.1.4 are:
7.1.4.1:
... Any function declared in a header may be additionally implemented as a function-like macro defined in the header, so if a library function is declared explicitly when its header is included, one of the techniques shown below can be used to ensure the declaration is not affected by such a macro. Any macro definition of a function can be suppressed locally by enclosing the name of the function in parentheses, because the name is then not followed by the left parenthesis that indicates expansion of a macro function name. For the same syntactic reason, it is permitted to take the address of a library function even if it is also defined as a macro.185) The use of #undef to remove any macro definition will also ensure that an actual function is referred to. ...
185 This means that an implementation shall provide an actual function for each library function, even if it also provides a macro for that function.
7.1.4.2:
Provided that a library function can be declared without reference to any type defined in a header, it is also permissible to declare the function and use it without including its
associated header.
The rest of the clauses are irrelevant. I don't see what 7.1.3.2 refers to as "as allowed by 7.1.4", except the definition of the library function in the same header as the function, i.e. the standard header, as a macro.
In summary, is the code above techincally undefined behavior? How about if string.h
was not included?
See Question&Answers more detail:
os