Module 1: Introduction to C

A Brief History of C

The C programming language was created by Dennis Ritchie at Bell Labs in the early 1970s, originally implemented on a DEC PDP-11 computer running the UNIX operating system. It evolved from earlier programming languages that influenced its design.

Language Evolution

Key Milestones in C Standardization

Year Standard Significance
1972-1978 Early C / K&R C Defined by Brian Kernighan and Dennis Ritchie in "The C Programming Language"
1989 ANSI C (C89) First standardized version by ANSI; introduced portability and standard libraries
1990 ISO C (C90) Adopted internationally by ISO, identical to ANSI C
1995 Amendment 1 Added wide-character support and new library functions
1999 C99 Introduced inline functions, variable-length arrays, and new data types like long long
2011 C11 Added multi-threading support, Unicode, and improved memory handling
2018 C18 Minor bug fixes and clarifications to the C11 standard

Did You Know? Over 90% of modern operating systems, compilers, and embedded systems are written in C or C-based languages.

C as a Middle-Level Language

C combines the best elements of high-level languages with the control and flexibility of assembly language.

Programming Language Spectrum:

Level Languages Characteristics
High Level Ada, Modula-2, Pascal, COBOL, FORTRAN, BASIC Abstracted from hardware, easier to read and write
Middle Level Java, C++, C, FORTH, Macro-assembler Balance between hardware control and programming convenience
Low Level Assembler Direct hardware manipulation, machine-specific

Key Characteristics of C as Middle-Level Language:

C as a Structured Language

C is a structured programming language that emphasizes compartmentalization of code and data.

Structured vs. Non-structured Languages:

Non-structured Languages Structured Languages
FORTRAN Pascal
BASIC Ada
COBOL C++
C
Java
Modula-2

Key Structural Features of C:

Example of Code Block in C:

if (x < 10) {
  printf("Too low, try again.\n");
  scanf("%d", &x);
}

The two statements between curly braces form a logical code block that executes together.
Such blocks ensure that multiple related actions are treated as one logical unit.

C as a Programmer's Language

Unlike languages designed for non-programmers (like COBOL and BASIC), C was created by and for working programmers.

Advantages for Programmers:

  • Few Restrictions: Maximum flexibility with minimal constraints
  • Efficiency: Nearly achieves assembly code efficiency with high-level structure
  • Stand-alone Functions: Modular programming approach
  • Compact Syntax: Small set of powerful keywords
  • Systems Programming: Ideal for operating systems and utilities
  • Portability: Code can run on different systems with minimal changes

Historical Applications:

Compilers vs. Interpreters

Understanding the difference between compilation and interpretation is crucial for C programming, as C was specifically designed as a compiled language.

Comparison Table:

Aspect Compiler Interpreter
Execution Method Converts entire program to machine code before execution Reads and executes source code line by line
Performance Faster execution (direct machine code) Slower execution (line-by-line processing)
Development Cycle Edit → Compile → Run Edit → Run
Error Detection All errors reported at compile time Errors detected during execution
Portability Machine-specific executable Same source code runs on different platforms
Memory Usage More efficient Less efficient

C as a Compiled Language:

Note: While C interpreters exist, serious C development almost always uses compilers for optimal performance and efficiency.

C Keywords and Reserved Words

C89 Standard Keywords (32 Keywords)

Complete List of C Keywords (32 Keywords)

Data Type Keywords
char double enum float int short long signed unsigned union void
Control Flow Keywords
if else switch case default for while do break continue goto case return
Storage Class Keywords
auto register static extern typedef
Type Qualifiers & Others
const volatile sizeof

C99 Additional Keywords (5 Keywords)

Keyword Purpose
Bool Boolean data type
Complex Complex numbers support
Imaginary Imaginary numbers support
inline Function inlining optimization
restrict Pointer optimization qualifier

Important Notes About Keywords:

  • Case Sensitivity: C is case-sensitive - else is a keyword, ELSE is not
  • Reserved Usage: Keywords cannot be used as variable or function names
  • Compiler Extensions: Many compilers add non-standard keywords for specific environments

Common Compiler Extension Keywords

Many C compilers include additional keywords to better exploit their specific operating environments:

Keyword Common Usage
asm, asm Inline assembly code
cdecl, pascal Function calling conventions
interrupt Interrupt service routines
near, far, huge Memory model specifications (8086 family)
cs, ds, es, ss Segment register access

Note: These extended keywords are compiler-specific and may not be available in all C compilers. Always check your compiler documentation.

Structure of a C Program or Basic Concepts of a C Program

All C programs consist of one or more functions, with main() being the essential starting point.

General Form of a C Program:

[Comments]
[Preprocessor Directives]
[Global Declarations]
[Function Declarations]
[Function Definitions]
main()
{
 [Declaration Section]
 [Executable Section]
}
  1. Comments

    • At the beginning of each program is a comment with a short description of the problem to be solved.
    • We can use the comments anywhere in the program.
    • The comments section is optional.
      Ex: 1. /* Program1: To find the sum of two numbers*/
      2. // Program2: To calculate the area and perimeter of circle
    • The symbol /* and ends with */ represents the multiline comment.
    • The symbol // can also be used for representing single line comment.
  2. Preprocessor directives

    • The preprocessor statements start with # symbol.
    • These statements instruct the compiler to include some of the files in the beginning of the program.
      Ex: #include<stdio.h>
      #include<math.h>
      are the files that the compiler includes in the beginning of the program.
    • The line containing #include<stdio.h> tells the compiler to allow our program to perform standard input and output 'stdio' operations.
    • The '#include' directive tells the compiler that we will be using parts of the standard function library.
    • Information about these functions is contained in a series of 'header files' (stdio.h).  .h says this file is a header file.
    • The pointed brackets < and > tell the compiler the exact location of this header file.
    • Using the preprocessor directives the user can define the constants also.
      Ex: #define PI 3.142
  3. Global Declarations

    • The variables that are declared above (before) the main program are called global variables.
    • The global variables can be accessed anywhere in the main program and in all the other functions.
  4. Function declarations and Definitions

    • In this section the functions are declared.
    • Immediately after the functions are declared, the functions can be defined.
  5. The program header: main()

    • Every program must have a main function.
    • Always the C program begins its execution from main.
  6. Body of the program

    • After the header or top lines is a set of braces ({ and }) containing a series of 'C' statements which comprise the 'body'- this is called the action portion of the program.
      #include <stdio.h>
      main(void) {
         /* action portion of the program*/
      }
    • The global variables can be accessed anywhere in the main program and in all the other functions.
  7. Declaration section

    • The variables that are used inside the function should be declared in the declaration section.
    • For example, consider the declaration shown below:
      int sum=0;
      int a;
      float b;
      Here, the variable sum is declared as an integer variable and it is initialized to zero.
      The variable a is declared as an integer variable whereas the variable b is declared as a floating point variable.
  8. Executable section

    • They represent the instructions given to the computer to perform a specific task.
    • The instructions can be input/output statements, expressions to be evaluated, simple assignment statements, control statements such as if statement, for statement etc.
    • Each executable statement ends with “;”. Example: Write a C program to display “Hello World”.
      #include <stdio.h>
      void main(void) {
         printf(“Hello World”);
      }

Key Structural Elements:

About the main() Function:

  • Although main is not a keyword, treat it as reserved
  • Don't use main as a variable name
  • Execution always begins at main()
  • Well-written C code uses main() as a high-level program outline

The C Standard Library and Linking

Why Libraries Are Essential

C provides very few built-in features through its keywords alone. Most useful tasks — such as input/output, math, or string handling — come from the Standard C Library. Without these libraries, even simple programs like printf("Hello World"); wouldn’t work!

The Linking Process

When you compile and run your C program, the compiler and linker work together to include both your code and the necessary library functions.

Step Description
1. Compilation The compiler converts source code (.c file) into object code (.obj or .o) and remembers external function names like printf or sqrt.
2. Linking The linker connects your object file with the appropriate library files (e.g., stdio.lib, math.lib).
3. Execution The final executable contains both your logic and the library code, ready to run as one program.

Library Characteristics

Technical Note: During linking, the linker automatically replaces placeholder offsets with real memory addresses so that all functions are properly connected before the program runs.

Building Blocks of C Programming

Essential Components Summary

Component Purpose Examples
Keywords Language fundamentals and control structures if, while, int, return
Standard Library Pre-built functionality for common tasks printf(), scanf(), strlen()
Functions Program organization and modularity main(), user_defined()
Linking Combining program components into executable Compiler/linker process

Best Practices for C Program Structure

  • Modular Design: Break programs into small, focused functions
  • Library Usage: Leverage standard library functions when possible
  • Clear main(): Use main() as a high-level program outline
  • Reusable Functions: Create your own library functions for repeated tasks
  • Standard Compliance: Stick to standard keywords for portability

Separate Compilation in C

What is Separate Compilation?

Separate compilation allows a C program to be divided across multiple source files, with each file compiled independently before being linked together.

Traditional vs Separate Compilation:

Aspect Single File Compilation Separate Compilation
Program Size Best for small programs Ideal for large projects
Compile Time Recompile entire program for any change Only recompile changed files
Team Development Difficult with multiple programmers Easy collaboration
Code Organization All code in one place Logical separation of functionality

Benefits of Separate Compilation:

  • Reduced Compile Time: Only modified files need recompilation
  • Team Collaboration: Multiple programmers can work on different files
  • Better Organization: Logical grouping of related functions
  • Code Reusability: Easily reuse compiled object files
  • Modular Development: Isolate and test individual components

Example Project Structure:

project/
├── main.c          (main program)
├── utils.c         (utility functions)
├── math_ops.c      (mathematical operations)
├── io_handlers.c   (input/output functions)
└── headers/
    ├── utils.h
    ├── math_ops.h
    └── io_handlers.h

The C Program Compilation Process

Three-Step Compilation Process:

Step Description Input Output
1. Program Creation Writing source code using a text editor Program logic and algorithms .c source files
2. Compilation Translating source code to machine code .c source files .o object files
3. Linking Combining object files with libraries .o files + libraries Executable file

Compilation Environments:

Integrated Development Environment (IDE)

  • Editor, compiler, and linker in one package
  • Automatic project management
  • Debugging tools included
  • Examples: Code::Blocks, Visual Studio, Eclipse

Stand-alone Compiler

  • Separate editor required
  • Command-line operation
  • More control over compilation process
  • Examples: GCC, Clang, MSVC command line

Important Requirements:

  • Text Files Only: Compilers require plain text files, not word processor documents
  • No Control Codes: Files must not contain special formatting characters
  • Compiler Specific: Exact commands vary between compilers
  • Documentation: Always consult your compiler's documentation

C Program Memory Map

Four Logical Memory Regions:

Conceptual Memory Layout:

Stack
Function calls, local variables
(grows downward)
Heap
Dynamic memory allocation
(grows upward)
Data Segment
Global and static variables
Code Segment
Program executable instructions

Detailed Memory Regions:

Memory Region Contents Characteristics
Code/Text Segment Executable program instructions Read-only, fixed size
Data Segment Global variables, static variables Fixed size, persists throughout program
Stack • Function return addresses
• Function arguments
• Local variables
• CPU state information
LIFO structure, automatic management
Heap Dynamically allocated memory Manual management, flexible size

Quick Summary (Easy to Remember)

Important Points to Remember

Detailed Memory Regions:

Memory Region Contents Characteristics
Code/Text Segment Executable program instructions Read-only, fixed size
Data Segment Global variables, static variables Fixed size, persists throughout program
Stack • Function return addresses
• Function arguments
• Local variables
• CPU state information
LIFO structure, automatic management
Heap Dynamically allocated memory Manual management, flexible size

Stack and Heap Memory Management

Stack Memory Characteristics:

  • Automatic Management: Memory allocated and freed automatically
  • Fast Access: Very efficient memory access
  • LIFO Structure: Last-In-First-Out organization
  • Function Scope: Tied to function calls and returns
  • Limited Size: Fixed maximum size per thread

Heap Memory Characteristics:

  • Manual Management: Programmer controls allocation/deallocation
  • Flexible Size: Can grow as needed (within system limits)
  • Global Access: Accessible from anywhere in program
  • Dynamic Allocation: Memory allocated at runtime
  • Slower Access: More overhead than stack

Memory Management Functions:

Function Purpose Memory Region
malloc() Allocate memory block Heap
calloc() Allocate and initialize to zero Heap
realloc() Resize allocated memory block Heap
free() Release allocated memory Heap

Note: The exact physical layout of memory regions varies between different CPU architectures and C implementations, but the logical structure remains consistent across platforms.

Practical Compilation Example (Fedora)

Separate Compilation Workflow:

Step 1: Create Source Files

$ gedit main.c & utils.c & utils.h

// main.c
#include <stdio.h>
#include "utils.h"

int main() {
  int result = add(5, 3);
  printf("Result: %d\n", result);
  return 0;
}

// utils.c
#include "utils.h"
int add(int a, int b) {
  return a + b;
}

// utils.h
#ifndef UTILS_H
#define UTILS_H
int add(int a, int b);
#endif

Step 2: Compile Separately

$ cc -c main.c
  # Generates main.o
$ cc -c utils.c
 # Generates utils.o

Step 3: Link and Run

$ cc main.o utils.o -o program
$ ./program

Key Advantages in Practice:

Review of Terms:

  • Source code: The text of a program that a user can read, commonly thought of as the program. The source code is input into the C compiler.
  • Object code: Translation of the source code of a program into machine code, which the computer can read and execute directly. Object code is the input to the linker.
  • Linker: A program that links separately compiled modules into one program. It also combines the functions in the Standard C library with the code that you wrote. The output of the linker is an executable program.
  • Library: A file containing the standard functions that your program can use. These functions include all I/O operations as well as other useful routines.
  • Compile time: The time during which your program is being compiled.
  • Run time: The time during which your program is executing.