tags:

views:

138

answers:

5

Could someone please explain me how extra functionality is added to C?

For example, C has no output function, so you can use printf() by including stdio.h, C doesn't know how to open a MessageBox so you include and use MessageBox() etc.

But how is this functionality implemented?

Do you have to use assembler in some way and access the Video RAM to have an output or something similar?

I know that MessageBox(), for example, is part of WinAPI but how is it implemented (though WinAPI is implemented in C)?

+5  A: 

Any of the functionality that interacts with the system is performed through the system call mechanism. Essentially this provides an interface between your code and the operating system. The library functions that you mention wrap some convenient functionality around various system calls to make it easier for your code to interact with the system at a higher level. You can, however, write the code to do this directly. For more information look up the syscall and ioctl functions. On Windows, there are more system calls and they are scattered throughout various libraries in the Windows API. This Dr. Dobb's article on Windows system calls goes into more detail

tvanfosson
This is UNIX-centric (but still very valuable).
paxdiablo
I'm showing my bias, even though I'm now mostly a .NET/C# programmer. Updated to provide some references for Windows.
tvanfosson
+1  A: 

At first you have the C compiler, which conforms to ANSI C standard. This is the language itself, no libraries included.

Then you have the standard library, where the printf function you've mentioned is to be found. This is built using C and ASM and is platform specific. For example in an embedded platform printf would print characters to a serial port or an lcd display. So platform specific code needs to be used. However the interface is common for all platforms.

Something similar happens with 3rd party libraries, like the WinAPI.

kgiannakakis
+1  A: 

For the printf part - it's part of the C Standard Library, which is a part of C. So the implementation of your C compiler or C Standard library can use all sort of tricks to make it work.

Let's take a simple example on how such a function can be implemented in Unix. Take putchar (simplified here - without returning anything). It outputs one character to standard output, which has the file descriptor number 1. The operation system provides a function called "write". A program can write into a file descriptor. So, putchar can use that function:

void putchar(int c) {
    unsigned char cc = c;
    write(1, &cc, 1);
}

Will write 1 byte to the file descriptor 1. The write function will tell the operation system about that wish:

void write(int fd, void * ptr, size_t size) {
    asm("....."
        "int 0x80"); 
}

It will usually just contain a small block of assembly lines that raises a software interrupt (in the sample above, it's the interrupt number 0x80). The CPU will switch into kernel mode and jump to some fixed address, from which the operation system can handle that interrupt. write will have written the system call number for write into some register and will have put the arguments into some memory location or into registers too, so that the operation system knows what to do at that point. The operation system will then send the bytes that should be written to the designated file/device (in case of stdout, it could be the terminal driver that is connected to the file descriptor), and will return from interrupt, making the CPU switch to user mode again.

That's the rough plan. There is more to it (putchar could buffer the output before doing the system call...) of course. But in principle, it works this way.

The MessageBox function too will call some system call in the end, that transfers control into the windows kernel in some or another way similar to the above explanation.

Johannes Schaub - litb
A: 

Often times libraries are written in "C". Most of the Win32 api is written in C. There are a few things you can't express directly in C, like 'syscall', 'int' and reading / writing to io ports.

Take a look at K&R they actually implement some system libraries in the book.

Mo Flanagan
+1  A: 

Realise that pretty much everything you do will result in the CPU reading numbers from some memory address, performing some calculation on them, or writing them to some memory address.

So most communication with the outside world - devices like your video card, network card etc. - basically boils down to reading from or writing to magic memory locations.

(This is a slight oversimplification, there are a few other things the CPU can do - I/O ports it can read/write numbers to, etc; these are not directly accessible from standard C, and typically C libraries that expose such functionality will have the relevant code written in assembler; but let's roll with it for now).

Hardware drivers written in C typically declare structs that describe the layout of the memory-mapped regions using familiar C types, obtain the addresses of the relevant regions, perform the appropriate casts then just use the resulting pointers like any others.

The OS typically wraps this sort of very hardware-specific code in some kind of mechanism that provides virtualisation (so your code can pretend it is talking to some standard idealised device, and the OS translates between that and what is actually in your machine) and privilege separation (so your code is prevented from doing things it's not supposed to and/or crashing other people's code). So the libraries you link to won't be talking to the hardware directly; they'll be calling the OS (typically using some form of syscall/interrupt/exception mechanism) which will do that for them. But the OS itself will be doing roughly what I describe above.

moonshadow