
printf()
and malloc()
calls invoke the C runtime library (libc). The C runtime library is a layer on top of the kernel, and may end up calling the kernel depending on circumstances.
The kernel provides somewhat primitive memory allocation via brk()
(extend/shrink the data segment), and mmap()
(map pages of memory into the process virtual address space). Libc's malloc()
internally manages memory it has obtained from the kernel, and tries to minimize system calls (among other things, it also tries to avoid excessive fragmentation, and tries to have good performance on multi-threaded programs, so has to make some compromises).
stdio
input/ouput (via *printf()/*scanf()
) is buffered, and ends up calling the kernel's write()/read()
system calls. By default, stderr
(the error stream) is unbuffered or line-buffered (ISO C §7.19.3 ¶7), so that errors can be seen immediately. stdin
and stdout
are line-buffered or unbuffered unless it can be determined they aren't attached to an interactive device, so that interactive prompts for input work correctly. stdin
and stdout
can be fully-buffered (block-buffered) if they refer to a disk file, or other non-interactive stream.
That means that error output is by default guaranteed to be seen as soon as you output a '\n'
(newline) character (unless you use setbuf()/setvbuf()
). Normal output additionally requires to be connected to a terminal or other interactive device to provide that guarantee.