4

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?

chqrlie
  • 131,814
  • 10
  • 121
  • 189
sadcat_1
  • 193
  • 10
  • 4
    Not C's fault. Ask the linker. – stark Jan 27 '22 at 21:02
  • 3
    This might help: [Why doesn't the linker complain of duplicate symbols?](https://stackoverflow.com/q/34454355/10077) – Fred Larson Jan 27 '22 at 21:18
  • By the way, if you want to replace `printf` in a defined way, define your own version with another name, such as `MyPrintf`, and then, inside a function, define `int (*printf)(const char * restrict,...) = MyPrintf`. While `printf` is reserved for use with file scope or external linkage, you can use it for your own purposes with block scope and no linkage. However, you would have to define it in each function you want to use it in. – Eric Postpischil Jan 27 '22 at 21:46

2 Answers2

5

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.

n. m. could be an AI
  • 112,515
  • 14
  • 128
  • 243
1

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.

pelya
  • 4,326
  • 2
  • 24
  • 23