8

When a C program is compiled it under goes in the order of pre-processor,compiler,assembler,linker. One of the main tasks for linker is to make code of library functions available to your program. Linker can link them in two ways static or dynamically..

stdio.h contains only declarations,no definitions are present in it. we only include stdio.h in program to say compiler about the return type and name of functions eg(printf(),scanf(),getc(),putc()...).. Then how printf() and scanf() are linked in the example program below?

  • If it is linking dynamically which "DLL" is responsible in linking??
  • Is total "C" Library is linked dynamically to program??
    #include "stdio.h"
 
    int main()
    {
      int n;
 
       printf("Enter an integer\n");
       scanf("%d", &n);
 
       if (n%2 == 0)
           printf("Even\n");
       else
           printf("Odd\n");
 
       return 0;
    } 
Peter - Reinstate Monica
  • 15,048
  • 4
  • 37
  • 62
  • 1
    Same way as you link C runtime (standard library) – Ivan Aksamentov - Drop Oct 29 '15 at 18:59
  • 1
    Your c program has a lot of things which you should avoid them in future. 1) **int main(){}** should be **int main(void){}**. 2) You should check **scanf()** for errors. 3) Why, I repead why do you need **\n** in here =>> **printf("Enter an integer\n");** ? 4) Is there any reason for you to not use **brackets** in if-else ? – Michi Oct 29 '15 at 19:12
  • 1
    @Michi 1) the correct signature is `int main(int argc, char *argv[])`, 4) Adding brackets around a single line of code in an `if` statement just wastes vertical space and clutters up the code. It's just a style issue and people are free to do it either way (but the indentation does need to be fixed no matter which style you prefer). – Carey Gregory Oct 29 '15 at 19:38
  • 1
    @CareyGregory And if there is no arguments ? The Standard says **int main(void){}** or **int main(int argc, char *argv[]){}**. Why only **int main(int argc, char *argv[]){}** please explain. – Michi Oct 29 '15 at 19:41
  • 1
    @CareyGregory About brackets, I was intended to know OPs answer, but if you insist then let me tell you that, just because there are optional things in c language it doesn't mean that you shouldn't use them. I know that in that peace of code is no problem by ignoring them, but at some point it will be. I think that people when they share their code should have more respect for that, but this is my personal opinion. – Michi Oct 29 '15 at 19:46
  • @Michi I stand corrected on `main(void)` being acceptable in the standard. However, adding braces around single lines of code isn't necessary, it adds clutter, and it causes no harm whatsoever as long as the future programmers who maintain it know what they're doing. – Carey Gregory Oct 29 '15 at 19:48
  • @CareyGregory I didn't said that he should use brackets in that code, what I was asking was: **4) Is there any reason for you to not use brackets in if-else ?** Was more a curiosity and nothing more. – Michi Oct 29 '15 at 19:50
  • @Michi You said he should avoid doing the things on your list. – Carey Gregory Oct 29 '15 at 19:58
  • @Michi I don't understand why you think you *don't* want a `\n` on the first call to `printf`. Without it the prompt may not be visible to the user. – zwol Oct 29 '15 at 20:03
  • @zwol there are a lot of ways to avoid that like =>> printf("Enter an integer:> "); or printf("Enter an integer\t");, but I will not going to argue with you about that :): – Michi Oct 29 '15 at 20:10
  • There are no DLLs, static linling, or dynamic linking in the C language. If you are interested in a particular implementation which may have these things, ask about that specific implementation. – n. m. could be an AI Nov 15 '15 at 10:29

4 Answers4

19

I think the question you are trying to ask is: “I know that functions like printf and scanf are implemented by the C runtime library. But I can use them without telling my compiler and/or IDE to link my program with the C runtime library. Why don’t I need to do that?”

The answer to that question is: “Programs that don’t need to be linked with the C runtime library are very, very rare. Even if you don’t explicitly use any library functions, you will still need the startup code, and the compiler might issue calls to memcpy, floating-point emulation functions, and so on ‘under the hood.’ Therefore, as a convenience, the compiler automatically links your program with the C runtime library, unless you tell it to not do that.”

You will have to consult the documentation for your compiler to learn how to tell it not to link in the C runtime library. GCC uses the -nostdlib command-line option. Below, I demonstrate the hoops you have to jump through to make that work...

$ cat > test.c
#include <stdio.h>
int main(void) { puts("hello world"); return 0; }
^D
$ gcc -nostdlib test.c && { ./a.out; echo $?; } 
/usr/bin/ld: warning: cannot find entry symbol _start
/tmp/cc8svIx5.o: In function ‘main’:
test.c:(.text+0xa): undefined reference to ‘puts’
collect2: error: ld returned 1 exit status

puts is obviously in the C library, but so is this mysterious "entry symbol _start". Turn off the C library and you have to provide that yourself, too...

$ cat > test.c
int _start(void) { return 0; }
^D
$ gcc -nostdlib test.c && { ./a.out; echo $?; }
Segmentation fault
139

It links now, but we get a segmentation fault, because _start has nowhere to return to! The operating system expects it to call _exit. OK, let's do that...

$ cat > test.c
extern void _exit(int);
void _start(void) { _exit(0); }
^D
$ gcc -nostdlib test.c && { ./a.out; echo $?; }
/tmp/ccuDrMQ9.o: In function `_start':
test.c:(.text+0xa): undefined reference to `_exit'
collect2: error: ld returned 1 exit status

... nuts, _exit is a function in the C runtime library, too! Raw system call time...

$ cat > test.c
#include <unistd.h>
#include <sys/syscall.h>
void _start(void) { syscall(SYS_exit, 0); }
^D
$ gcc -nostdlib test.c && { ./a.out; echo $?; }
/tmp/cchtZnbP.o: In function `_start':
test.c:(.text+0x14): undefined reference to `syscall'
collect2: error: ld returned 1 exit status

... nope, syscall is also a function in the C runtime. I guess we just have to use assembly!

$ cat > test.S
#include <sys/syscall.h>
.text
.globl _start
.type _start, @function
_start:
        movq $SYS_exit, %rax
        movq $0, %rdi
        syscall
$ gcc -nostdlib test.S && { ./a.out; echo $?; }
0

And that, finally, works. On my computer. It wouldn't work on a different operating system, with a different assembly-level convention for system calls.

You might now be wondering what the heck -nostdlib is even good for, if you have to drop down to assembly language just to make system calls. It's intended to be used when compiling completely self-contained, low-level system programs like the bootloader, the kernel, and (parts of) the C runtime itself — things that were going to have to implement their own everything anyway.

If we had it to do all over again from scratch, it might well make sense to separate out a low-level language-independent runtime, with just the syscall wrappers, language-independent process startup code, and the functions that any language's compiler might need to call "under the hood" (memcpy, _Unwind_RaiseException, __muldi3, that sort of thing). The problem with that idea is it rapidly suffers mission creep — do you include errno? Generic threading primitives? (Which ones, with which semantics?) The dynamic linker? An implementation of malloc, which several of the above things need? Windows's ntdll.dll began as this concept, and it's 1.8MB on disk in Windows 10, which is (slightly) bigger than libc.so + ld.so on my Linux partition. And it's rare and difficult to write a program that only uses ntdll.dll, even if you're Microsoft (the only example I'm sure of is csrss.exe, which might as well be a kernel component).

zwol
  • 135,547
  • 38
  • 252
  • 361
5

Generally, standard C libraries are linked dynamically. This is mainly because of the reasons that once a program has been statically linked, the code in it is fixed forever. If someone finds and fixes a bug in printf or scanf, then every program has to be linked again in order to pick up the fixed code.

In case of dynamic linking, none of the executable files (created after linking) contains a copy of the code for printf or scanf. If a new, fixed, version of printf is available, then it is picked up at run time.

haccks
  • 104,019
  • 25
  • 176
  • 264
  • 1
    Thanks for reply..If it is linking dynamically which "DLL" is responsible in linking?? and Is total "C" Library is linked dynamically to program?? –  Nov 01 '15 at 17:04
  • 1
    @LearNer; *.If it is linking dynamically which "DLL" is responsible in linking??*: I have no idea about that. * Is total "C" Library is linked dynamically to program??* : I said *generally*. I can't say it with surety. A C compiler writer/developer can explain these in much detail. I just gave you a rough idea. – haccks Nov 01 '15 at 17:45
  • 1
    If an implementation bundles and statically links functions like `printf`, `scanf`, etc. then it can let programmers select from different versions of the function which are maximally suitable for their particular use cases. While it might be nice to be able to fix some C runtime bugs or quirks, having corner-case behaviors change spontaneously is often not a good thing. – supercat Apr 21 '21 at 20:59
  • I think the main reason for dynamic linking is that you don't want the code for those functions replicated a million times on disk and a thousand times in memory. The standard library exists *once* (OK, perhaps once *per version*), on disk and in RAM repectively. – Peter - Reinstate Monica Jun 07 '21 at 11:37
4
-static-libstdc++

When the g++ program is used to link a C++ program, it normally automatically links against libstdc++. If libstdc++ is available as a shared library, and the -static option is not used, then this links against the shared version of libstdc++. That is normally fine. However, it is sometimes useful to freeze the version of libstdc++ used by the program without going all the way to a fully static link. The -static-libstdc++ option directs the g++ driver to link libstdc++ statically, without necessarily linking other libraries statically.

For more details, please check this thread. How can i statically link standard library to my c++ program?

Community
  • 1
  • 1
Validus Oculus
  • 2,756
  • 1
  • 25
  • 34
  • 3
    It worth mentioning that this answer describes linking of GNU C++ Standard Library for GNU GCC compiler, which are popular major compiler and C++ standard library, but not unique ones. Also it has nothing to do with C library where `printf()` and `scanf()` are defined. – Ivan Aksamentov - Drop Oct 29 '15 at 19:15
-3

They are linked statically, that way your program will be able to determine if there are any compilation errors before preceding to run the program.

scerrecrow
  • 259
  • 1
  • 9