0

Building a C program should be no rocket science! I recently had to return to this kind of business since many years of absence.

Interestingly I encounter the exact opposite as asked in Why is #include <stdio.h> not required to use printf()?

#if 0
#include <stdio.h>
#endif
void main() { /* Yes, I know! */
    printf("Hello, World!\n");
}

I want to compile and link the above example.

If I use the Digital Mars C Compiler all it's gonna take is

dmc -c hello.c
optlink hello.obj,hello.exe

Done.

OK, it was that simple because the DMC toolchain backstage did some work for me.

On the one hand the compiler inserted a hint into the object file saying the external "_printf" can be found in library SNN

0082  COMENT  0 9f 53 4e 4e                                    ..SNN
008b  EXTDEF  e 5f 5f 61 63 72 74 75 73 65 64 5f 63 6f 6e  0   .__acrtused_con.
              7 5f 70 72 69 6e 74 66  0                        ._printf.
00a8  PUB386  0  1  5 5f 6d 61 69 6e  0  0  0  0  0            ..._main.....

And on the other hand the linker is searching libraries to satisfy unresolved externals

Loading hello from hello.obj
Searching LIBRARY files
Loading constart from ..\lib\SNN.lib
Loading _printf from ..\lib\SNN.lib

There is the option

-NL no default library

to make the compiler stop doing this additional work. I now get a plain object file.

Hey, and therefore it's no surprise the linker is yelling at me

hello.obj(hello)
 Error 42: Symbol Undefined __acrtused_con
hello.obj(hello)
 Error 42: Symbol Undefined _printf

Because it's my turn now to tell the linker where to get the missing stuff from

optlink hello.obj,hello.exe,,SNN.lib

Again done.

Now let's use the Microsoft toolchain...

cl -c hello.c
link hello.obj

Boom!

hello.obj : error LNK2019: unresolved external symbol "_printf" in function "_main".
hello.exe : fatal error LNK1120: 1 unresolved external.

For some reason the linker will only produce a hello.exe when the source file includes <stdio.h>.

What kind of "new" magic feature did M$ include in their toolchain?

PS: Somehow the statement in MSDN does not hold true: If you link your program from the command line without a compiler option that specifies a C runtime library, the linker will use the statically linked CRT libraries: libcmt.lib, libvcruntime.lib, and libucrt.lib.

vl106
  • 11
  • 2
  • BTW: I am using cl and link as installed by Microsoft Visual Studio 2019... – vl106 Feb 20 '23 at 16:57
  • Based on the question you linked, your program has undefined behavior. Am I correct that you're asking why those two compilers behaving differently/weirdly for a program that has undefined behavior? – Brian61354270 Feb 20 '23 at 17:07
  • The header probably has a [`#pragma comment(lib)`](https://learn.microsoft.com/en-us/cpp/preprocessor/comment-c-cpp) in there somewhere, telling the linker which libraries to look at to find functions declared in the header. – Igor Tandetnik Feb 20 '23 at 17:53
  • Upon closer inspection: `printf` is implemented directly in the header as an inline function, in terms of `_vfprintf_l`. The obj file doesn't mention `_printf` at all. `_vfprintf_l` is itself an inline function, calling `__stdio_common_vfprintf`, which is, finally, defined in `libucrt.lib` – Igor Tandetnik Feb 20 '23 at 18:28
  • `printf` as a standalone function still exists in `legacy_stdio_definitions.lib`. You may link with that, should you be so inclined. [Details here](https://learn.microsoft.com/en-us/cpp/porting/visual-cpp-change-history-2003-2015), in particular "The `printf` and `scanf` family of functions are now defined inline" section. – Igor Tandetnik Feb 20 '23 at 18:31
  • Thanks a bunch @IgorTandetnik for enlightening this. – vl106 Feb 21 '23 at 16:04

0 Answers0