Fundamentals of C Programming: Key Concepts and Examples

The C language employs a sequence of characters from the source character set to create executable programs. This guide covers essential components including Linux OS usage, data types, constants and variables, operators, input/output operations, control statements, arrays, pointers, functions, structures, unions, and memory management.

Basic Program Structure

#include<stdio.h>
int main() {
    printf("hello world!\n");
    return 0;
}

The main function serves as the program's entry point, and return 0 marks its exit.

Performing Simple Calculations

printf("%d\n", 23 + 43);
printf("23+43=%d\n", 23 + 43);

The %d format specifier indicates where an integer value should be inserted in the output.

Standard Library Functions

Library functions provide pre-built routines to simplify coding. Documentation can be found at standard C library references.

The printf() Function

This function outputs text to the console. It does not automatically append a newline character.

Width Specification:

printf("%5d\n", 123); // Outputs: "  123"
printf("%-5d\n", 123); // Outputs: "123  "
printf("%12f\n", 123.456); // Outputs: "  123.456000"

Sign Display:

printf("%+d\n", 12); // Outputs: "+12"
printf("%+d\n", -12); // Outputs: "-12"

Precision Control:

printf("%.3f\n", 0.5); // Outputs: "0.500"
printf("%.3f\n", 0.54321); // Outputs: "0.543"
printf("%8.2f\n", 0.54321); // Outputs: "    0.54"

Partial String Output:

printf("%8.2s\n", "123456789"); // Outputs: "      12"
printf("%-8.2s\n", "123456789"); // Outputs: "12      "

The scanf() Function

This function reads user input from the keyboard. In some compilers like MSVC, a definition may be needed to suppress warnings:

#define _CRT_SECURE_NO_WARNINGS 1

Basic Usage:

int val1, val2;
float num1, num2;
scanf("%d %d %f %f", &val1, &val2, &num1, &num2);
printf("%d %d %f %f", val1, val2, num1, num2);

Return Value: scanf() returns an integer indicating the number of successfully read items, or EOF on end-of-file.

Placeholders:

  • %[]: Matches a set of characters.
  • %c: Reads a single character.
  • %s: Reads a string until whitespace.

Assignment Suppression: The * character can be used to read but discard input matching a specifier.

int yr, mo, dy;
scanf("%d%*c%d%*c%d", &yr, &mo, &dy);

Character I/O Functions

getchar() reads a single character from stdin, while putchar() writes one to stdout.

int ch = getchar();
putchar(ch);

These function are useful for skipping lines, counting characters, or ignoring whitespace.

Blocks and Scope

A block is a compound statement enclosed in braces {}. Scope defines where a variable is accessible.

Block Scope: Variables declared inside a block are local to that block.

{
    int localVar = 99;
    printf("%d", localVar);
}
// localVar not accessible here

File Scope: Variables declared outside all functions have global scope.

int globalCounter = 7;
void display() {
    printf("%d", globalCounter);
}

C Keywords

C reserves 32 keywords for language use. These include storage class specifiers (auto, static, register, extern), type specifiers (char, int, float, etc.), control flow keywords (if, for, while, etc.), and qualifiers (const, volatile).

The sizeof Operator: This operator returns the size in bytes of a type or expression.

size_t intSize = sizeof(int);
size_t varSize = sizeof(myVar);

Use the %zu format specifier to print size_t values.

Signed and Unsigned Types: The signed and unsigned keywords modify enteger types to specify whether they represent both positive and negative values, or only non-negative values, respectively.

C Statements

Statements in C can be categorized as:

  • Null statements (;)
  • Expression statements
  • Function call statements
  • Compound statements (blocks)
  • Control statements (branching, looping, jumps)

Computation Basics

Algorithms define the steps for computation. C programs are typically compiled into machine code. Input is line-oriented, terminated by pressing Enter.

Basic I/O:

int userInput;
double userValue;
scanf("%d", &userInput);
printf("%d\n", userInput);
scanf("%lf", &userValue);
printf("%f", userValue);

Format Specifiers: Common specifiers include %d for int, %ld for long, %f for float/double, %c for char, %s for strings, %p for pointers, and %x for hexadecimal.

Escape Sequences: Special characters like \n (newline), \t (tab), \\ (backslash), and \" (double quote) are represented with escape sequences.

Variables and Data Types

A variable is a named memory location for storing data. Identifiers must start with a letter or underscore, followed by letters, digits, or underscores.

Variable Definition and Initialization:

int counter; // Declaration
counter = 0; // Assignment
int index = 0; // Initialization

Fundamental Types:

  • Integers: short, int, long, long long (signed/unsigned variants).
  • Floating-point: float, double, long double.
  • Character: char (may be signed or unsigned by default).
  • Boolean: _Bool (from C99, use <stdbool.h> for bool, true, false).

Expressions and Operators

An expression combines operators and operands to compute a value.

Arithmetic Operators: +, -, *, /, %. Integer division truncates the fractional part. The modulo operator % works only with integers.

int quotient = 6 / 4; // Result: 1
float result = 6.0 / 4; // Result: 1.5
int remainder = 7 % -5; // Result: 2 (sign follows first operand)

Assignment Operators: =, +=, -=, *=, /=, %=.

Increment/Decrement: ++, -- (prefix and postfix).

int x = 10;
printf("%d", x++); // Prints 10, then x becomes 11
printf("%d", ++x); // x becomes 12, then prints 12

Operator Precedence and Associativity: Operators have defined precedence levels; consult a reference table for details. Parentheses can be used to enforce evaluation order.

Swapping Variables:

int temp = a;
a = b;
b = temp;

Control Flow: Decision Making

Relational Operators: ==, !=, >, >=, <, <= evaluate to 1 (true) or 0 (false).

The if-else Statement:

const int PASS_MARK = 60;
int score;
scanf("%d", &score);
if (score >= PASS_MARK) {
    printf("Passed\n");
} else {
    printf("Failed\n");
}

Always use braces {} for multi-statement blocks.

Comments: Use // for single-line comments and /* ... */ for multi-line comments.

Control Flow: Looping

The while Loop:

int num, digitCount = 0;
scanf("%d", &num);
do {
    num /= 10;
    digitCount++;
} while (num > 0);
printf("Digits: %d\n", digitCount);

The for Loop:

int n, factorial = 1;
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
    factorial *= i;
}
printf("%d! = %d\n", n, factorial);

Loop Selection:

  • Use for for a known number of iterations.
  • Use do-while when the body must execute at least once.
  • Use while when the iteration count is uncertain.

Advanced Control Flow

Logical Operators: ! (NOT), && (AND), || (OR). Logical expressions short-circuit evaluation.

Conditional Operator: ? :

int absValue = (x >= 0) ? x : -x;

Comma Operator: Evaluates expressions left-to-right, yielding the value of the rightmost expression.

Nested and Cascaded if-else:

if (a > b) {
    if (a > c) max = a;
    else max = c;
} else {
    if (b > c) max = b;
    else max = c;
}

The switch Statement:

int choice;
scanf("%d", &choice);
switch (choice) {
    case 1: printf("Option 1\n"); break;
    case 2: printf("Option 2\n"); break;
    default: printf("Invalid\n");
}

Loop Control with break and continue: break exits the innermost loop; continue skips to the next iteration.

The goto Statement:

for (...) {
    for (...) {
        if (error) goto cleanup;
    }
}
cleanup:
    // Cleanup code

Use sparingly as it can harm code readability.

Common Programming Examples

Number Guessing Game:

#include <stdlib.h>
#include <time.h>
int main() {
    srand(time(0));
    int secret = rand() % 100 + 1;
    int guess, attempts = 0;
    do {
        printf("Guess (1-100): ");
        scanf("%d", &guess);
        attempts++;
        if (guess > secret) printf("Too high\n");
        else if (guess < secret) printf("Too low\n");
    } while (guess != secret);
    printf("Correct! Attempts: %d\n", attempts);
}

Integer Reversal:

int original, reversed = 0;
scanf("%d", &original);
int working = original;
while (working > 0) {
    reversed = reversed * 10 + working % 10;
    working /= 10;
}
printf("%d reversed is %d\n", original, reversed);

Arrays

An array stores a fixed-size sequential collection of elements of the same type.

Declaration and Initialization:

int scores[100];
int primes[] = {2, 3, 5, 7, 11}; // Size inferred
int zeros[10] = {0}; // All elements zero

Array Traversal:

for (int idx = 0; idx < arrayLength; idx++) {
    printf("%d ", arr[idx]);
}

Array indices start at 0. Accessing out-of-bounds indices leads to undefined behavior.

Array Size: Use sizeof(arr) / sizeof(arr[0]) to compute the number of elements.

Arrays as Function Parameters: When passing an array to a function, it decays to a pointer to its first element.

void processArray(int data[], int len) {
    for (int i = 0; i < len; i++) {
        // Process data[i]
    }
}
// Equivalent prototypes:
// void processArray(int *data, int len);
// void processArray(int [], int);

Two-Dimensional Arrays:

int matrix[3][5];
for (int row = 0; row < 3; row++) {
    for (int col = 0; col < 5; col++) {
        matrix[row][col] = row * col;
    }
}
// Initialization:
int grid[][3] = {{1,2,3}, {4,5,6}};

Functions

Functions encapsulate reusable code segments.

Definition and Call:

int maximum(int x, int y) {
    return (x > y) ? x : y;
}
int main() {
    int a = 5, b = 8;
    int m = maximum(a, b);
    printf("Max: %d\n", m);
}

Function Prototype: A declaration that specifies the function's return type, name, and parameter types.

int add(int, int); // Prototype
int main() {
    int sum = add(3, 4);
}
int add(int x, int y) { return x + y; } // Definition

Parameter Passing: C uses pass-by-value. To modify an argument, pass its address.

void increment(int *ptr) {
    (*ptr)++;
}
int main() {
    int val = 10;
    increment(&val);
    printf("%d\n", val); // Prints 11
}

Local Variables: Variables declared inside a function have automatic storage duration and are not initialized by default.

Algorithms on Arrays

Linear Search:

int findIndex(int key, int arr[], int size) {
    for (int i = 0; i < size; i++) {
        if (arr[i] == key) return i;
    }
    return -1;
}

Binary Search (requires sorted array):

int binarySearch(int key, int arr[], int size) {
    int low = 0, high = size - 1;
    while (low <= high) {
        int mid = (low + high) / 2;
        if (arr[mid] == key) return mid;
        else if (arr[mid] < key) low = mid + 1;
        else high = mid - 1;
    }
    return -1;
}

Selection Sort:

void selectionSort(int arr[], int n) {
    for (int i = 0; i < n-1; i++) {
        int minIdx = i;
        for (int j = i+1; j < n; j++) {
            if (arr[j] < arr[minIdx]) minIdx = j;
        }
        int temp = arr[i];
        arr[i] = arr[minIdx];
        arr[minIdx] = temp;
    }
}

Prime Number Algorithms:

  1. Trial division up to n-1.
  2. Skip even numbers after checking 2.
  3. Trial division up to sqrt(n).
  4. Sieve of Eratosthenes for generating primes up to a limit.

Pointers

A pointer variable stores a memory address.

Pointer Declaration and Usage:

int value = 42;
int *ptr = &value; // ptr holds address of value
printf("Value: %d\n", *ptr); // Dereference to access value
*ptr = 99; // Modify value via pointer

Pointer Arithmetic: Adding an integer n to a pointer advances it by n * sizeof(type) bytes.

int arr[] = {10, 20, 30, 40};
int *p = arr;
printf("%d\n", *(p + 1)); // Prints 20

Dynamic Memory Allocation:

#include <stdlib.h>
int *dynamicArray = (int*)malloc(10 * sizeof(int));
if (dynamicArray != NULL) {
    // Use the array
    free(dynamicArray); // Release memory
}

Pointers and const:

  • const int *p: Pointer to constant data (data cannot be modified via p).
  • int *const p: Constant pointer (pointer itself cannot point elsewhere).
  • const int *const p: Both are constant.

Strings

In C, strings are null-terminated character arrays ('\0').

String Initialization:

char greeting[] = {"Hello"}; // Array with null terminator
char *msg = "World"; // Pointer to string literal
char buffer[20] = ""; // Empty string

String literals are immutable; use arrays for modifiable strings.

String Input/Output:

char name[50];
printf("Enter name: ");
scanf("%49s", name); // Limit input length
printf("Hello, %s\n", name);

String Functions from <string.h>:

  • strlen(s): Returns length excluding null terminator.
  • strcmp(s1, s2): Compares strings lexicographically.
  • strcpy(dest, src): Copies string.
  • strcat(dest, src): Concatenates strings.
  • strchr(s, c): Finds first occurrence of character c.

Safe Alternatives: strncpy, strncat, strncmp allow specifying maximum lengths to prevent buffer overflows.

Implementing String Functions:

int myStrlen(const char *s) {
    int len = 0;
    while (*s++) len++;
    return len;
}

int myStrcmp(const char *s1, const char *s2) {
    while (*s1 && (*s1 == *s2)) {
        s1++; s2++;
    }
    return *(unsigned char*)s1 - *(unsigned char*)s2;
}

char* myStrcpy(char *dest, const char *src) {
    char *start = dest;
    while ((*dest++ = *src++));
    return start;
}

Tags: c programming Arrays pointers functions Control Flow

Posted on Sun, 18 Oct 2026 16:17:13 +0000 by bothwell