A Brief Introduction To C Programming
Last updated: Dec 5, 2021
C is a general-purpose, procedural programming language developed in 1972 by Dennis Ritchie and Ken Thompson at Bell Telephone Laboratories. C was initially designed for the UNIX operating system and first implemented on the DEC PDP-11. The UNIX operating system, the C compiler and most of the applications were all written in C.
Even after all this time, C remains incredibly popular and can be found in a wide variety of application domains. For example, C features in operating systems such as Windows, MacOS and Linux, embedded systems, databases, compilers, applications, IoT (Internet of Things) devices and much more. Essentially, nearly everything that we touch today, from our cars to our washing machines, contains some form of computer processor influenced by — if not directly programmed in — the C language.
C was initially introduced as a high-level programming language because it provided an abstraction from the computer’s Instruction Set Architecture, enabling engineers to write programs without being tied to any particular hardware or system. Nowadays, most people would consider C a middle-to-low level programming language because it can be used to write both system and application software.
With C, engineers can work closely with the host machine’s hardware by using memory pointers or by seamlessly embedding assembly language into applications to manipulate registers, processor status flags, I/O ports, or interrupt vectors and handlers.
On the flip side, engineers can use C to write applications with complex data structures, variables, functions, and other things found within high-level programming languages whilst still compiling the application directly into assembly language. Compared to other high-level languages such as C# or Java, which are first compiled into an intermediate language and then interpreted by a virtual machine into machine instructions, this makes C incredibly efficient and fast.
Furthermore, because C enables the engineer to exercise fine control over the external dependencies and libraries, it is possible to write code that depends on absolutely nothing, allowing core software such as operating systems and bootloaders to be written from the ground up.
Of course, such a lack of restriction and flexibility comes with the limitation that C trusts the engineer to know what they are doing and not make mistakes. There are no guards to prevent security vulnerabilities like buffer overflow attacks, and there is no built-in garbage collection to assist with memory management, unlike managed code. Moreover, C does not provide direct support for error/exception handling. By convention, C expects the programmer to prevent errors from occurring in the first place and test return values from functions.
Yet, while other languages may offer these newer language features, their compilers and libraries are still typically written in C.
Ultimately, the C programming language is a fantastic tool for systems programming as it enables direct control over the memory and hardware. But, if working higher up in the stack on software that will run on an operating system, such as a desktop application, it may be more suitable to use other programming languages that facilitate memory management and offer feature-rich libraries to achieve rapid results.