Back Back

C Programming Language

C is a general-purpose, procedural programming language developed in 1972 by Dennis Ritchie at Bell Labs. Known for its efficiency and control, it remains a cornerstone of modern programming, influencing languages like C++, Java, and Python. C is widely used in operating systems, embedded systems, and high-performance applications.

Origin

Developed between 1969-1973 at Bell Labs to rewrite the Unix operating system, replacing assembly language for better portability.

Features

Low-level memory access, minimal runtime, simple syntax, structured programming, and portability across platforms.

Limitations

Lacks object-oriented programming, no built-in exception handling, manual memory management, and no native support for namespaces.

Why Learn C?

Did You Know?

C was created to rewrite the Unix operating system, making it one of the first portable OS kernels. Its influence extends to nearly all modern operating systems.

Getting Started with C

Basic Structure

#include  // Standard I/O library

int main() { // Main function where execution begins
    printf("Hello, World!\n");
    return 0; // Indicates successful execution
}

Every C program requires a main() function as the entry point. The #include directive imports header files for standard library functions.

Compilation Process

  1. Preprocessing: Expands macros and includes header files
  2. Compilation: Converts C code to assembly code
  3. Assembly: Translates assembly to machine code (object file)
  4. Linking: Combines object files into an executable

gcc program.c -o program

Compile with GCC to create an executable named 'program'

Data Types in C

Basic Data Types

Type Size (bytes) Range Format Specifier
char 1 -128 to 127 %c
int 2 or 4 -32,768 to 32,767 (2 bytes) or -2,147,483,648 to 2,147,483,647 (4 bytes) %d
float 4 1.2E-38 to 3.4E+38 %f
double 8 2.3E-308 to 1.7E+308 %lf

Example:

#include 

int main() {
    char grade = 'A';
    int age = 25;
    float height = 5.9;
    double salary = 75000.50;
    
    printf("Grade: %c\n", grade);
    printf("Age: %d\n", age);
    printf("Height: %.1f\n", height);
    printf("Salary: %.2lf\n", salary);
    
    return 0;
}

Type Modifiers

  • signed - Stores positive and negative values (default)
  • unsigned - Stores only positive values, doubling positive range
  • short - Reduces storage size for smaller range
  • long - Increases storage size for larger range
unsigned int positiveOnly = 40000;
short int smallNumber = 100;
long int bigNumber = 1234567890;

Derived Data Types

  • Arrays - Collection of elements of the same type
  • Pointers - Store memory addresses
  • Structures - Group different data types
  • Unions - Share memory for different data types
int numbers[5]; // Array
int *ptr;       // Pointer
struct student { // Structure
    char name[50];
    int age;
};
union data {    // Union
    int i;
    float f;
};

Variables & Constants

Variables

Variables are named storage locations for data. They must be declared with a data type before use.

Rules for Naming Variables:

  • Can contain letters, digits, and underscores
  • Must begin with a letter or underscore
  • Case-sensitive (age ≠ Age ≠ AGE)
  • Cannot use reserved keywords (e.g., int, float)
int age = 25;          // Integer variable
float price = 19.99;   // Floating point
char letter = 'A';     // Character
int x, y, z;           // Multiple declarations
x = y = z = 50;        // Same value to multiple variables

Constants

Constants are fixed values that cannot be modified during program execution.

Types of Constants:

  • Literal Constants: Direct values like 100, 3.14, 'A'
  • #define Preprocessor: #define PI 3.14159
  • const Keyword: const float PI = 3.14159;
#include 
#define PI 3.14159    // Macro constant

int main() {
    const int DAYS = 7;  // const keyword
    printf("PI: %.5f\n", PI);
    printf("Days in week: %d\n", DAYS);
    return 0;
}

Input & Output in C

printf() - Output Function

The printf() function outputs formatted data to the console (stdout).

Format Specifiers:

  • %d - Integer
  • %f - Float
  • %c - Character
  • %s - String
  • %lf - Double
  • %x - Hexadecimal
#include 

int main() {
    int num = 10;
    float fnum = 3.14;
    char letter = 'A';
    
    printf("Integer: %d\n", num);
    printf("Float: %.2f\n", fnum); // 2 decimal places
    printf("Character: %c\n", letter);
    printf("All together: %d, %.2f, %c\n", num, fnum, letter);
    
    return 0;
}

scanf() - Input Function

The scanf() function reads formatted input from the keyboard (stdin).

Important Notes:

  • Requires address-of operator (&) for non-array variables
  • Strings (char arrays) don't need &
  • Beware of buffer overflow with strings; use width specifiers
#include 

int main() {
    int age;
    float height;
    char name[50];
    
    printf("Enter your age: ");
    scanf("%d", &age);
    
    printf("Enter your height: ");
    scanf("%f", &height);
    
    printf("Enter your name: ");
    scanf("%49s", name); // Limit input to prevent overflow
    
    printf("\nName: %s\nAge: %d\nHeight: %.1f\n", 
           name, age, height);
    
    return 0;
}

Other I/O Functions

getchar() & putchar()

Single character input/output

char c = getchar();
putchar(c);

gets() & puts()

String I/O (unsafe - use fgets() instead)

char str[100];
gets(str);    // Deprecated, unsafe
puts(str);

fgets() & fputs()

Safe string input/output

char str[100];
fgets(str, 100, stdin);
fputs(str, stdout);

Operators in C

Arithmetic Operators

Operator Description Example Result
+ Addition 5 + 2 7
- Subtraction 5 - 2 3
* Multiplication 5 * 2 10
/ Division 5 / 2 2 (integer division)
% Modulus 5 % 2 1
#include 

int main() {
    int a = 10, b = 3;
    
    printf("Sum: %d\n", a + b);
    printf("Difference: %d\n", a - b);
    printf("Product: %d\n", a * b);
    printf("Quotient: %d\n", a / b);
    printf("Remainder: %d\n", a % b);
    
    return 0;
}

Relational Operators

Compare values, returning 1 (true) or 0 (false)

  • == Equal to
  • != Not equal
  • > Greater than
  • < Less than
  • >= Greater or equal
  • <= Less or equal
int x = 5, y = 10;
printf("%d\n", x > y);  // 0 (false)

Logical Operators

Combine multiple conditions

  • && AND (both true)
  • || OR (either true)
  • ! NOT (reverses result)
int age = 25, salary = 50000;
if (age > 21 && salary > 30000) {
    printf("Eligible for loan\n");
}

Bitwise Operators

Operate on individual bits

  • & AND
  • | OR
  • ^ XOR
  • ~ NOT
  • << Left shift
  • >> Right shift
unsigned char a = 5; // 00000101
unsigned char b = 9; // 00001001
printf("%d\n", a & b); // 00000001 → 1

Assignment Operators

Assign values to variables

  • = Simple assignment
  • += Add and assign
  • -= Subtract and assign
  • *= Multiply and assign
  • /= Divide and assign
  • %= Modulus and assign
int x = 10;
x += 5;  // x = x + 5 → 15
x *= 2;  // x = x * 2 → 30

Other Operators

  • ?: Ternary operator (conditional)
  • sizeof() Returns size in bytes
  • & Address of operator
  • * Pointer dereference
  • , Comma operator
int a = 5, b = 10;
int max = (a > b) ? a : b;  // Ternary
printf("%zu\n", sizeof(int));  // Sizeof
int *ptr = &a;              // Address
printf("%d\n", *ptr);       // Dereference

Control Flow Statements

if-else Statements

Execute code based on conditions

Syntax:

if (condition1) {
    // code if condition1 true
} else if (condition2) {
    // code if condition2 true
} else {
    // code if all false
}

Example:

#include 

int main() {
    int num = 10;
    
    if (num > 0) {
        printf("Positive\n");
    } else if (num < 0) {
        printf("Negative\n");
    } else {
        printf("Zero\n");
    }
    
    return 0;
}

switch Statement

Multi-way branch based on a value

Syntax:

switch (expression) {
    case constant1:
        // code
        break;
    case constant2:
        // code
        break;
    default:
        // code if no match
}

Example:

#include 

int main() {
    char grade = 'B';
    
    switch (grade) {
        case 'A':
            printf("Excellent!\n");
            break;
        case 'B':
            printf("Good\n");
            break;
        case 'C':
            printf("Average\n");
            break;
        default:
            printf("Invalid grade\n");
    }
    
    return 0;
}

while Loop

Repeats while condition is true

while (condition) {
    // code to repeat
}
#include 

int main() {
    int i = 1;
    while (i <= 5) {
        printf("%d ", i);
        i++;
    }
    // Output: 1 2 3 4 5
    return 0;
}

do-while Loop

Executes at least once, then repeats while condition is true

do {
    // code to repeat
} while (condition);
#include 

int main() {
    int i = 1;
    do {
        printf("%d ", i);
        i++;
    } while (i <= 5);
    // Output: 1 2 3 4 5
    return 0;
}

for Loop

Compact loop with initialization, condition, and increment

for (init; condition; increment) {
    // code to repeat
}
#include 

int main() {
    for (int i = 1; i <= 5; i++) {
        printf("%d ", i);
    }
    // Output: 1 2 3 4 5
    return 0;
}

Loop Control Statements

break

Exits the loop immediately

#include 

int main() {
    for (int i = 1; i <= 10; i++) {
        if (i == 5) break;
        printf("%d ", i);
    }
    // Output: 1 2 3 4
    return 0;
}

continue

Skips the current iteration

#include 

int main() {
    for (int i = 1; i <= 5; i++) {
        if (i == 3) continue;
        printf("%d ", i);
    }
    // Output: 1 2 4 5
    return 0;
}

goto

Jumps to a labeled statement (use sparingly)

#include 

int main() {
    int i = 1;
start:
    printf("%d ", i);
    i++;
    if (i <= 5) goto start;
    // Output: 1 2 3 4 5
    return 0;
}

Functions in C

Function Basics

Functions are reusable blocks of code that perform specific tasks, improving modularity and readability.

Function Components:

  • Return Type: Data type of the returned value (use void if none)
  • Function Name: Unique identifier for calling the function
  • Parameters: Input values (optional)
  • Function Body: Code to execute
#include 

// Function declaration (prototype)
int add(int a, int b);

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

// Function definition
int add(int a, int b) {
    return a + b;
}

Parameter Passing

C supports two ways to pass parameters: by value (copy) and by reference (using pointers).

Pass by Value vs. Pass by Reference:

  • Pass by Value: Copies the value; changes don't affect the original
  • Pass by Reference: Passes the address; changes affect the original
#include 

void swapByValue(int a, int b) {
    int temp = a;
    a = b;
    b = temp;
}

void swapByReference(int *a, int *b) {
    int temp = *a;
    *a = *b;
    *b = temp;
}

int main() {
    int x = 5, y = 10;
    swapByValue(x, y);
    printf("After swapByValue: x=%d, y=%d\n", x, y); // No change
    swapByReference(&x, &y);
    printf("After swapByReference: x=%d, y=%d\n", x, y); // Swapped
    return 0;
}

Function Types

  • Library Functions: Built-in functions like printf(), scanf()
  • User-defined Functions: Custom functions created by the programmer
  • Recursive Functions: Functions that call themselves

Recursion Example:

#include 

int factorial(int n) {
    if (n == 0 || n == 1) return 1;
    return n * factorial(n - 1);
}

int main() {
    printf("5! = %d\n", factorial(5)); // 120
    return 0;
}

Storage Classes

Storage classes define the scope and lifetime of variables.

Class Scope Lifetime
auto Local Function
register Local Function
static Local/Global Program
extern Global Program
#include 

void counter() {
    static int count = 0; // Retains value between calls
    count++;
    printf("Count: %d\n", count);
}

int main() {
    counter(); // Count: 1
    counter(); // Count: 2
    return 0;
}

Arrays in C

One-Dimensional Arrays

Arrays store multiple elements of the same data type in contiguous memory locations.

Declaration & Initialization:

// Declaration
int numbers[5];

// Initialization
int primes[5] = {2, 3, 5, 7, 11};

// Partial initialization
int arr[5] = {1, 2}; // Rest are 0

// Size from initializer
int days[] = {31, 28, 31}; // Size 3

Example:

#include 

int main() {
    int arr[5] = {10, 20, 30, 40, 50};
    
    for (int i = 0; i < 5; i++) {
        printf("arr[%d] = %d\n", i, arr[i]);
    }
    
    return 0;
}

Multi-Dimensional Arrays

Arrays of arrays, commonly used for matrices or tables.

2D Array Example:

#include 

int main() {
    int matrix[2][3] = {
        {1, 2, 3},
        {4, 5, 6}
    };
    
    for (int i = 0; i < 2; i++) {
        for (int j = 0; j < 3; j++) {
            printf("%d ", matrix[i][j]);
        }
        printf("\n");
    }
    
    return 0;
}

Array to Function:

#include 

void printArray(int arr[], int size) {
    for (int i = 0; i < size; i++) {
        printf("%d ", arr[i]);
    }
}

int main() {
    int nums[3] = {1, 2, 3};
    printArray(nums, 3);
    return 0;
}

Pointers in C

Pointer Basics

Pointers store memory addresses, enabling direct memory manipulation.

Key Concepts:

  • & - Address of operator
  • * - Dereference operator
  • Pointer arithmetic (++, --, +, -)
  • NULL pointer - Points to nothing
#include 

int main() {
    int num = 10;
    int *ptr = # // ptr stores address of num
    
    printf("Value: %d\n", num);    // 10
    printf("Address: %p\n", (void*)&num); // Memory address
    printf("Pointer value: %d\n", *ptr); // 10
    
    *ptr = 20; // Change value through pointer
    printf("New value: %d\n", num); // 20
    
    return 0;
}

Pointers and Arrays

Arrays and pointers are closely related; an array name is a pointer to its first element.

Array Name as Pointer:

#include 

int main() {
    int arr[3] = {10, 20, 30};
    int *ptr = arr; // Points to first element
    
    printf("%d\n", *ptr);    // 10
    printf("%d\n", *(ptr+1)); // 20
    printf("%d\n", arr[1]);  // 20
    printf("%d\n", *(arr+1)); // 20
    return 0;
}

Pointer to Pointer:

#include 

int main() {
    int num = 10;
    int *ptr = #
    int **pptr = &ptr;
    
    printf("%d\n", **pptr); // 10
    return 0;
}

Pointers and Functions

Pointers enable pass-by-reference, allowing functions to modify original variables.

#include 

void swap(int *a, int *b) {
    int temp = *a;
    *a = *b;
    *b = temp;
}

int main() {
    int x = 5, y = 10;
    swap(&x, &y);
    printf("x = %d, y = %d\n", x, y); // x=10, y=5
    return 0;
}

Dynamic Memory Allocation

Allocate memory at runtime using malloc(), calloc(), realloc(), and free with free().

Functions:

  • malloc(size): Allocates uninitialized memory
  • calloc(n, size): Allocates and initializes to zero
  • realloc(ptr, size): Resizes allocated memory
  • free(ptr): Releases memory
#include 
#include 

int main() {
    int *arr = (int*)malloc(5 * sizeof(int));
    if (arr == NULL) {
        printf("Memory allocation failed\n");
        return 1;
    }
    
    for (int i = 0; i < 5; i++) {
        arr[i] = i + 1;
    }
    
    for (int i = 0; i < 5; i++) {
        printf("%d ", arr[i]);
    }
    
    free(arr); // Release memory
    return 0;
}

Strings in C

String Basics

Strings are arrays of characters terminated by a null character (\0).

Declaration & Initialization:

char str1[10] = "Hello"; // Null-terminated
char str2[] = "World";   // Size inferred
char *str3 = "C Programming"; // String literal

Example:

#include 

int main() {
    char str[] = "Hello, World!";
    printf("%s\n", str);
    for (int i = 0; str[i] != '\0'; i++) {
        printf("%c ", str[i]);
    }
    return 0;
}

String Functions

The string.h library provides functions for string manipulation.

Common Functions:

  • strlen(str): Returns string length
  • strcpy(dest, src): Copies string
  • strcat(dest, src): Concatenates strings
  • strcmp(str1, str2): Compares strings
#include 
#include 

int main() {
    char str1[20] = "Hello";
    char str2[20] = "World";
    
    printf("Length of str1: %zu\n", strlen(str1));
    strcat(str1, " ");
    strcat(str1, str2);
    printf("Concatenated: %s\n", str1);
    printf("Comparison: %d\n", strcmp(str1, "Hello World"));
    
    return 0;
}

Structures and Unions

Structures

Structures group different data types under a single name.

Syntax:

struct structureName {
    type member1;
    type member2;
    // ...
};

Example:

#include 

struct student {
    char name[50];
    int age;
    float gpa;
};

int main() {
    struct student s1 = {"John Doe", 20, 3.5};
    printf("Name: %s, Age: %d, GPA: %.2f\n", 
           s1.name, s1.age, s1.gpa);
    return 0;
}

Unions

Unions allow different data types to share the same memory location.

Syntax:

union unionName {
    type member1;
    type member2;
    // ...
};

Example:

#include 

union data {
    int i;
    float f;
    char c;
};

int main() {
    union data d;
    d.i = 10;
    printf("Integer: %d\n", d.i);
    d.f = 3.14;
    printf("Float: %.2f\n", d.f);
    d.c = 'A';
    printf("Char: %c\n", d.c);
    return 0;
}

File Handling in C

File Operations

C provides functions to read from and write to files using stdio.h.

Key Functions:

  • fopen(filename, mode): Opens a file
  • fclose(file): Closes a file
  • fprintf(file, format, ...): Writes to a file
  • fscanf(file, format, ...): Reads from a file
#include 

int main() {
    FILE *fp = fopen("example.txt", "w");
    if (fp == NULL) {
        printf("Error opening file\n");
        return 1;
    }
    
    fprintf(fp, "Hello, File Handling!\n");
    fclose(fp);
    return 0;
}

Reading from Files

Read data from files using functions like fscanf() or fgets().

#include 

int main() {
    FILE *fp = fopen("example.txt", "r");
    if (fp == NULL) {
        printf("Error opening file\n");
        return 1;
    }
    
    char buffer[100];
    while (fgets(buffer, 100, fp) != NULL) {
        printf("%s", buffer);
    }
    
    fclose(fp);
    return 0;
}

Preprocessor Directives

Common Directives

Preprocessor directives are processed before compilation, starting with #.

Key Directives:

  • #include: Includes header files
  • #define: Defines macros or constants
  • #ifdef, #ifndef: Conditional compilation
  • #undef: Undefines a macro
#include 
#define MAX 100

int main() {
    printf("Max value: %d\n", MAX);
    return 0;
}

Conditional Compilation

Control which code is compiled based on conditions.

#include 
#define DEBUG 1

int main() {
    #ifdef DEBUG
        printf("Debug mode enabled\n");
    #else
        printf("Debug mode disabled\n");
    #endif
    return 0;
}

Recursion in C

Recursion Basics

Recursion occurs when a function calls itself to solve a smaller instance of the same problem.

Key Components:

  • Base Case: Condition to stop recursion
  • Recursive Case: Function calls itself with modified input
#include 

int factorial(int n) {
    if (n == 0 || n == 1) { // Base case
        return 1;
    }
    return n * factorial(n - 1); // Recursive case
}

int main() {
    printf("5! = %d\n", factorial(5)); // 120
    return 0;
}

Fibonacci Sequence

A common example of recursion to generate Fibonacci numbers.

#include 

int fibonacci(int n) {
    if (n <= 1) return n; // Base case
    return fibonacci(n - 1) + fibonacci(n - 2); // Recursive case
}

int main() {
    for (int i = 0; i < 10; i++) {
        printf("%d ", fibonacci(i));
    }
    // Output: 0 1 1 2 3 5 8 13 21 34
    return 0;
}

Error Handling in C

Basic Error Handling

C lacks built-in exception handling; errors are managed using return codes and errno.

#include 
#include 

int main() {
    FILE *fp = fopen("nonexistent.txt", "r");
    if (fp == NULL) {
        perror("Error opening file");
        printf("Error code: %d\n", errno);
        return 1;
    }
    fclose(fp);
    return 0;
}

Custom Error Handling

Use return values and conditionals to handle errors gracefully.

#include 

int divide(int a, int b, int *result) {
    if (b == 0) {
        return -1; // Error code
    }
    *result = a / b;
    return 0; // Success
}

int main() {
    int result;
    if (divide(10, 0, &result) == -1) {
        printf("Error: Division by zero\n");
    } else {
        printf("Result: %d\n", result);
    }
    return 0;
}

C Programming Quiz

Test Your Knowledge

Answer the following questions to reinforce your understanding of C programming concepts.

1. What is the output of the following code?

#include 

int main() {
    int x = 5;
    printf("%d\n", x++ + ++x);
    return 0;
}

Answer: 12

Explanation: The expression x++ + ++x involves undefined behavior due to multiple modifications of x without a sequence point. However, in many compilers, ++x increments x to 6 first, then x++ uses the current value (6) and increments x to 7. Thus, the expression evaluates as 6 + 6 = 12.

2. What does the following function return for n = 3?

int recursiveSum(int n) {
    if (n <= 0) return 0;
    return n + recursiveSum(n - 1);
}

Answer: 6

Explanation: The function calculates the sum of numbers from 1 to n. For n = 3, it computes 3 + recursiveSum(2), where recursiveSum(2) = 2 + recursiveSum(1), and recursiveSum(1) = 1 + recursiveSum(0) = 1. Thus, 3 + 2 + 1 = 6.

3. What is wrong with this code?

#include 

int main() {
    char str[5];
    strcpy(str, "Hello");
    printf("%s\n", str);
    return 0;
}

Answer: Buffer overflow

Explanation: The array str[5] can hold 4 characters plus the null terminator. The string "Hello" has 5 characters plus the null terminator (6 bytes total), causing a buffer overflow. Use char str[6] or larger.

4. What is the size of the following structure on a 32-bit system?

struct example {
    char a;
    int b;
};

Answer: 8 bytes

Explanation: On a 32-bit system, char is 1 byte, and int is 4 bytes. Due to padding for alignment, the structure is padded to 8 bytes (1 byte for a, 3 bytes padding, 4 bytes for b).

5. What does this code print?

#include 

int main() {
    int arr[] = {1, 2, 3};
    int *ptr = arr;
    printf("%d\n", *(ptr + 2));
    return 0;
}

Answer: 3

Explanation: ptr points to the first element of arr. *(ptr + 2) accesses the third element (arr[2]), which is 3.


Learn C Programming by Tutorials Point


Download C Programming Detailed Notes PDF View C Programming Detailed Notes PDF

Try Yourself


C Compiler