Consider the next piece of code:
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
int printf(const char *format, ...)
{
va_list args;
return 1;
}
int main()
{
printf("Hello there");
return 0;
}
And indeed, printf prints nothing. Meaning, the compiler 'prefer' this function over the one declared in <stdio.h>. But C doesn't allow function overriding, and from my understanding, it should throw an error of conflicting errors.
Can anyone explain this behavior?
CodePudding user response:
The C standard says (7.1.3 Reserved identifiers):
- 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.
- 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.
- 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.
So when <stdio.h> is included, printf is reserved as an identifier with file scope in the name space of ordinary identifiers. In addition, printf is always reserved as an identifier with external linkage, even if <stdio.h> is not included.
7.1.4 Use of library functions does not allow to define a function with a reserved name.
In most implementations such definition will silently replace the library function, but the standard does not guarantee anything.
CodePudding user response:
It fails to compile by MSVC.
https://godbolt.org/z/Y1o14jj39
The answer is that on Linux the linker will try to use your local function first, and only then it will search for the function inside system libraries, and that's not an error for various historical reasons.
And yes, printf can be defined inside several libraries, the last loaded library will take a priority. This is a feature! You can override any system call by setting LD_PRELOAD environment variable to the path of your own shared library with that system call.
