Mastering Arrays in C: From Basic Concepts to Practical Applications

1. Array Fundamentals

An array is a contiguous block of memory that stores elements of the same data type. Unlike individual variables, arrays enable efficient storage and manipulation of multiple related values using a single identifier and an index.

2. One-Dimensional Arrays

2.1 Declaring One-Dimensional Arrays

The declaration processs follows a systematic approach:

  1. Specify the element type followed by a name
  2. Append square brackets containing the element count
  3. The complete declaration represents a collection of that type

Example 1: Five integer elements

int values[5];

Example 2: Five pointers to integers

int *ptr_array[5];

Example 3: Five arrays, each containing ten integers (2D array)

int matrix[5][10];

Example 4: Five functon pointers, each accepting two integers and returning an integer

int (*func_ptr[5])(int, int);

2.2 Array Size Calculation

#include <stdio.h>

int main(void)
{
    int data[6] = {0};

    size_t total_bytes = sizeof(data);
    size_t element_bytes = sizeof(data[0]);
    size_t element_count = sizeof(data) / sizeof(data[0]);

    printf("Total size: %zu bytes\n", total_bytes);
    printf("Element size: %zu bytes\n", element_bytes);
    printf("Element count: %zu\n", element_count);

    return 0;
}
Total size: 24 bytes
Element size: 4 bytes
Element count: 6

2.3 Array Initialization Methods

Full initialization:

int numbers[5] = {10, 20, 30, 40, 50};
// Alternatively, the dimension can be omitted:
// int numbers[] = {10, 20, 30, 40, 50};

Partial initialization:

int partial[5] = {1, 2, 3};  // Remaining elements default to 0

Zero initialization:

int zeroed[5] = {0};  // All elements become 0
int also_zero[5] = {};  // Also valid, all elements become 0

Designated initializer (C99):

int designated[5] = {[1] = 100, [3] = 300};

2.4 Array Element Manipulation

Arrays require element-by-element operations. Direct assignment between arrays is not permitted.

Example 1: Input and display

#include <stdio.h>

int main(void)
{
    int buffer[5] = {0};
    size_t count = sizeof(buffer) / sizeof(buffer[0]);

    for (size_t i = 0; i < count; i++)
    {
        scanf("%d", buffer + i);
    }

    for (size_t i = 0; i < count; i++)
    {
        printf("%d ", buffer[i]);
    }
    printf("\n");

    return 0;
}

Example 2: Finding maximum and minimum values

#include <stdio.h>

int main(void)
{
    int dataset[10] = {0};
    size_t len = sizeof(dataset) / sizeof(dataset[0]);

    for (size_t i = 0; i < len; i++)
    {
        scanf("%d", &dataset[i]);
    }

    int max_val = dataset[0];
    int min_val = dataset[0];

    for (size_t i = 1; i < len; i++)
    {
        if (dataset[i] > max_val)
            max_val = dataset[i];
        if (dataset[i] < min_val)
            min_val = dataset[i];
    }

    printf("Maximum: %d\n", max_val);
    printf("Minimum: %d\n", min_val);

    return 0;
}

Example 3: Array reversal

#include <stdio.h>

int main(void)
{
    int data[10] = {0};
    size_t len = sizeof(data) / sizeof(data[0]);

    for (size_t i = 0; i < len; i++)
    {
        scanf("%d", &data[i]);
    }

    for (size_t i = 0, j = len - 1; i < j; i++, j--)
    {
        data[i] ^= data[j];
        data[j] ^= data[i];
        data[i] ^= data[j];
    }

    for (size_t i = 0; i < len; i++)
    {
        printf("%d ", data[i]);
    }
    printf("\n");

    return 0;
}

Example 4: Sorting algorithms

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(void)
{
    int data[10] = {0};
    size_t len = sizeof(data) / sizeof(data[0]);

    srand(time(NULL));

    for (size_t i = 0; i < len; i++)
    {
        data[i] = rand() % 100 + 1;
    }

    printf("Before sorting:\n");
    for (size_t i = 0; i < len; i++)
    {
        printf("%d ", data[i]);
    }
    printf("\n");

    // Bubble sort implementation
    for (size_t i = 0; i < len - 1; i++)
    {
        for (size_t j = 0; j < len - 1 - i; j++)
        {
            if (data[j] > data[j + 1])
            {
                data[j] ^= data[j + 1];
                data[j + 1] ^= data[j];
                data[j] ^= data[j + 1];
            }
        }
    }

    printf("After sorting:\n");
    for (size_t i = 0; i < len; i++)
    {
        printf("%d ", data[i]);
    }
    printf("\n");

    return 0;
}

3. Two-Dimensional Arrays

3.1 Determining Dimensions

#include <stdio.h>

int main(void)
{
    int grid[3][4] = {{0}};

    size_t rows = sizeof(grid) / sizeof(grid[0]);
    size_t cols = sizeof(grid[0]) / sizeof(grid[0][0]);

    printf("Rows: %zu, Columns: %zu\n", rows, cols);

    return 0;
}
Rows: 3, Columns: 4

3.2 Initialization Strategies

Nested braces (row-by-row):

int matrix1[3][4] = {
    {1, 2},
    {5, 6},
    {9, 10, 11}
};

Flat initialization:

int matrix2[3][4] = {1, 2, 5, 6, 9, 10, 11};

Both approaches populate elements in row-major order. Unspecified elements initialize to zero.

3.3 Element Access Patterns

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(void)
{
    int grid[3][4] = {0};
    size_t rows = sizeof(grid) / sizeof(grid[0]);
    size_t cols = sizeof(grid[0]) / sizeof(grid[0][0]);

    srand(time(NULL));

    for (size_t i = 0; i < rows * cols; i++)
    {
        *(&grid[0][0] + i) = rand() % 100 + 1;
    }

    for (size_t i = 0; i < rows; i++)
    {
        for (size_t j = 0; j < cols; j++)
        {
            printf("%4d ", grid[i][j]);
        }
        printf("\n");
    }

    return 0;
}

4. Character Arrays (Strings)

4.1 Initialization Approaches

Character-by-character (not recommended):

char greeting[5] = {'h', 'e', 'l', 'l', 'o'};

String literal (recommended):

char greeting[6] = "hello";  // Compiler appends '\0' automatically

The null terminator \0 marks the end of a string and requires allocation space.

4.2 Traversal Techniques

Loop-based iteration:

#include <stdio.h>

int main(void)
{
    char message[6] = "hello";

    for (size_t i = 0; i < sizeof(message); i++)
    {
        putchar(message[i]);
        putchar(' ');
    }
    putchar('\n');

    return 0;
}

Direct string output:

#include <stdio.h>

int main(void)
{
    char text[32] = "embedded programming";

    printf("%s\n", text);

    return 0;
}

4.3 sizeof Versus strlen

#include <stdio.h>
#include <string.h>

int main(void)
{
    char text[32] = "embedded";

    printf("sizeof: %zu bytes (includes null terminator)\n", sizeof(text));
    printf("strlen: %zu characters (excludes null terminator)\n", strlen(text));

    return 0;
}
sizeof: 32 bytes
strlen: 8 characters

Key distinction: sizeof returns the total allocated memory including \0, while strlen counts actual characters before the null terminator.

4.4 Input Methods for Character Arrays

Using scanf:

#include <stdio.h>

int main(void)
{
    char input[64] = {0};

    scanf("%63s", input);  // Limit to prevent overflow
    printf("%s\n", input);

    return 0;
}

Using fgets (preferred for safety):

#include <stdio.h>

int main(void)
{
    char buffer[128] = {0};
    char *result = NULL;

    result = fgets(buffer, sizeof(buffer), stdin);
    if (result != NULL)
    {
        // Remove trailing newline if present
        size_t len = strlen(buffer);
        if (len > 0 && buffer[len - 1] == '\n')
        {
            buffer[len - 1] = '\0';
        }
        printf("%s\n", buffer);
    }

    return 0;
}

5. Two-Dimensional Character Arrays

char names[3][128] = {
    "Alice",
    "Bob",
    "Charlie"
};

Each row functions as an independent string storage.

6. Practical Exercises

Exercise 1: String Length Without strlen

#include <stdio.h>

int main(void)
{
    char text[128] = {0};
    size_t length = 0;

    fgets(text, sizeof(text), stdin);

    // Remove newline
    size_t i = 0;
    while (text[i] != '\0')
    {
        if (text[i] == '\n')
        {
            text[i] = '\0';
            break;
        }
        i++;
    }

    // Calculate length manually
    length = 0;
    while (text[length] != '\0')
    {
        length++;
    }

    printf("Length: %zu\n", length);

    return 0;
}

Exercise 2: String Copy Operation

#include <stdio.h>

int main(void)
{
    char source[128] = {0};
    char destination[128] = {0};

    fgets(source, sizeof(source), stdin);

    // Remove newline
    size_t src_len = 0;
    while (source[src_len] != '\0' && source[src_len] != '\n')
    {
        src_len++;
    }
    source[src_len] = '\0';

    // Copy character by character
    for (size_t i = 0; i <= src_len; i++)
    {
        destination[i] = source[i];
    }

    printf("Copied: %s\n", destination);

    return 0;
}

Exercise 3: String Concatenation

#include <stdio.h>
#include <string.h>

int main(void)
{
    char str1[256] = {0};
    char str2[128] = {0};

    printf("First string: ");
    fgets(str1, sizeof(str1), stdin);
    str1[strcspn(str1, "\n")] = '\0';

    printf("Second string: ");
    fgets(str2, sizeof(str2), stdin);
    str2[strcspn(str2, "\n")] = '\0';

    size_t pos = strlen(str1);
    for (size_t i = 0; str2[i] != '\0'; i++)
    {
        str1[pos + i] = str2[i];
    }

    printf("Concatenated: %s\n", str1);

    return 0;
}

Exercise 4: Character Search

#include <stdio.h>
#include <string.h>

int main(void)
{
    char text[128] = {0};
    char target;

    printf("Enter text: ");
    fgets(text, sizeof(text), stdin);
    text[strcspn(text, "\n")] = '\0';

    printf("Character to find: ");
    scanf("%c", &target);

    int index = -1;
    for (size_t i = 0; text[i] != '\0'; i++)
    {
        if (text[i] == target)
        {
            index = (int)i;
            break;
        }
    }

    if (index >= 0)
    {
        printf("Found at index: %d\n", index);
    }
    else
    {
        printf("Character not found\n");
    }

    return 0;
}

Exercise 5: String Insertion at Position

#include <stdio.h>
#include <string.h>

int main(void)
{
    char original[256] = {0};
    char insertion[128] = {0};
    char result[384] = {0};
    int position = 0;

    printf("Original string: ");
    fgets(original, sizeof(original), stdin);
    original[strcspn(original, "\n")] = '\0';

    printf("String to insert: ");
    fgets(insertion, sizeof(insertion), stdin);
    insertion[strcspn(insertion, "\n")] = '\0';

    printf("Position: ");
    scanf("%d", &position);

    size_t orig_len = strlen(original);
    size_t insert_len = strlen(insertion);

    // Handle position beyond string length
    if (position >= (int)orig_len)
    {
        strcpy(result, original);
        strcat(result, insertion);
    }
    else
    {
        // Copy before insertion point
        for (size_t i = 0; i < (size_t)position; i++)
        {
            result[i] = original[i];
        }

        // Insert new string
        for (size_t i = 0; i < insert_len; i++)
        {
            result[position + i] = insertion[i];
        }

        // Copy remaining characters
        for (size_t i = (size_t)position; i < orig_len; i++)
        {
            result[insert_len + i] = original[i];
        }
    }

    printf("Result: %s\n", result);

    return 0;
}

7. Array-Name Semantics

The array name behaves differently depending on context:

Context Behavior
sizeof(array_name) Represents total type size
&array_name Adress of the entire array
All other contexts Equivalent to &array_name[0] (pointer to first element)
#include <stdio.h>

int main(void)
{
    int data[5] = {1, 2, 3, 4, 5};

    printf("data:     %p\n", (void *)data);
    printf("&data[0]: %p\n", (void *)&data[0]);
    printf("&data:    %p\n", (void *)&data);

    printf("sizeof(data): %zu\n", sizeof(data));

    return 0;
}

The addresses of data and &data[0] are numerically equal, but their types differ: int* versus int (*)[5].

Tags: c programming Arrays strings character arrays Memory Management

Posted on Sun, 20 Sep 2026 16:33:17 +0000 by ichversuchte