google-site-verification: google61fe8ba583a51912.html
Arrays in C

Arrays are fundamental data structures in C that allow you to store multiple elements of the same type in contiguous memory locations. They provide efficient indexed access to elements and form the foundation for more complex data structures.


Table of Contents

  1. What are Arrays?
  2. Array Declaration
  3. Array Initialization
  4. Accessing Array Elements
  5. Array Size and Memory Layout
  6. Multidimensional Arrays
  7. Arrays and Pointers
  8. Passing Arrays to Functions
  9. Array of Pointers
  10. Common Array Operations
  11. Variable Length Arrays (C99)
  12. Array Limitations and Pitfalls
  13. Best Practices

What are Arrays?

An array is a collection of elements of the same data type stored in contiguous memory locations. Each element can be accessed by its index (position) in the array.

Key Characteristics

  • Homogeneous: All elements must be of the same type
  • Contiguous: Elements are stored sequentially in memory
  • Fixed Size: Size is determined at compile time (except VLA)
  • Zero-based Indexing: First element is at index 0
  • Direct Access: Any element can be accessed in O(1) time

Visual Representation

Memory: [1000] [1004] [1008] [1012] [1016] Index: 0 1 2 3 4 Value: 5 10 15 20 25

Array Declaration

Syntax

data_type array_name[array_size];

Examples

int numbers[10]; // array of 10 integers float temperatures[7]; // array of 7 floats char name[50]; // array of 50 characters double matrix[5][5]; // 2D array (5x5)

Important Notes

  • array_size must be a constant expression in traditional C
  • Size must be positive integer
  • Elements are uninitialized (contain garbage values)
const int SIZE = 100; int valid[SIZE]; // OK if SIZE is constant int n = 50; int invalid[n]; // Not allowed in C89, but allowed in C99 (VLA)

Array Initialization

1. Initialization at Declaration

// Full initialization int numbers[5] = {10, 20, 30, 40, 50}; // Partial initialization (remaining elements set to 0) int numbers[5] = {10, 20}; // {10, 20, 0, 0, 0} // Initialize all elements to 0 int zeros[10] = {0}; // All elements set to 0 // Initialize all elements to a specific value (not directly supported) int all_fives[10] = {5}; // {5, 0, 0, 0, ...} NOT {5,5,5,5...} // Compiler determines size int auto_size[] = {1, 2, 3, 4, 5}; // size inferred as 5 // Designated initializers (C99) int arr[10] = {[0] = 1, [5] = 2, [9] = 3}; // {1,0,0,0,0,2,0,0,0,3}

2. Character Array Initialization

// String initialization char str1[] = "Hello"; // {'H','e','l','l','o','\0'} char str2[6] = "Hello"; // Same as above char str3[10] = "Hello"; // {'H','e','l','l','o','\0',0,0,0,0} // Character by character char str4[] = {'H', 'e', 'l', 'l', 'o', '\0'};

3. Multidimensional Array Initialization

// 2D array initialization int matrix[2][3] = { {1, 2, 3}, {4, 5, 6} }; // Flattened initialization int matrix2[2][3] = {1, 2, 3, 4, 5, 6}; // Partial initialization int matrix3[2][3] = { {1, 2}, // third element defaults to 0 {4} // rest default to 0 }; // {{1,2,0}, {4,0,0}}

4. Static Initialization

static int counts[10] = {1, 2, 3}; // Static arrays are zero-initialized by default

Accessing Array Elements

Basic Access

#include <stdio.h> int main() { int numbers[5] = {10, 20, 30, 40, 50}; // Access individual elements printf("First element: %d\n", numbers[0]); // 10 printf("Third element: %d\n", numbers[2]); // 30 printf("Last element: %d\n", numbers[4]); // 50 // Modify elements numbers[1] = 25; printf("Modified second: %d\n", numbers[1]); // 25 return 0; }

Array Traversal

#include <stdio.h> int main() { int scores[] = {85, 92, 78, 90, 88}; int size = sizeof(scores) / sizeof(scores[0]); // Using for loop printf("All scores: "); for (int i = 0; i < size; i++) { printf("%d ", scores[i]); } printf("\n"); // Calculate sum and average int sum = 0; for (int i = 0; i < size; i++) { sum += scores[i]; } double average = (double)sum / size; printf("Sum: %d, Average: %.2f\n", sum, average); // Find maximum int max = scores[0]; for (int i = 1; i < size; i++) { if (scores[i] > max) { max = scores[i]; } } printf("Maximum: %d\n", max); return 0; }

Access with Pointers

int numbers[5] = {10, 20, 30, 40, 50}; // Array name is a constant pointer to first element int *ptr = numbers; // points to numbers[0] // Pointer arithmetic printf("%d\n", *ptr); // 10 printf("%d\n", *(ptr + 2)); // 30 (numbers[2]) printf("%d\n", ptr[3]); // 40 (ptr[3] same as numbers[3]) // Differences: ptr is variable, numbers is constant ptr++; // OK, now points to numbers[1] // numbers++; // ERROR: numbers is constant

Array Size and Memory Layout

Determining Array Size

#include <stdio.h> int main() { int numbers[] = {10, 20, 30, 40, 50}; // Total bytes occupied printf("Total size: %zu bytes\n", sizeof(numbers)); // 20 bytes (5 * 4) // Size of one element printf("Element size: %zu bytes\n", sizeof(numbers[0])); // 4 bytes // Number of elements int count = sizeof(numbers) / sizeof(numbers[0]); printf("Number of elements: %d\n", count); // 5 return 0; }

Memory Layout

#include <stdio.h> int main() { int arr[5] = {10, 20, 30, 40, 50}; printf("Array memory layout:\n"); for (int i = 0; i < 5; i++) { printf("arr[%d] = %-4d at address %p\n", i, arr[i], (void*)&arr[i]); } // Demonstrate contiguous memory printf("\nAddress difference between elements:\n"); printf("&arr[1] - &arr[0] = %td bytes\n", (char*)&arr[1] - (char*)&arr[0]); // Should be sizeof(int) return 0; }

Output:

Array memory layout: arr[0] = 10 at address 0x7fff5fbff7a0 arr[1] = 20 at address 0x7fff5fbff7a4 arr[2] = 30 at address 0x7fff5fbff7a8 arr[3] = 40 at address 0x7fff5fbff7ac arr[4] = 50 at address 0x7fff5fbff7b0 Address difference between elements: &arr[1] - &arr[0] = 4 bytes

Multidimensional Arrays

2D Arrays (Matrices)

#include <stdio.h> int main() { // Declaration and initialization int matrix[3][4] = { {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12} }; // Accessing elements printf("matrix[1][2] = %d\n", matrix[1][2]); // 7 (row 1, col 2) // Traversing 2D array printf("Matrix:\n"); for (int i = 0; i < 3; i++) { for (int j = 0; j < 4; j++) { printf("%4d", matrix[i][j]); } printf("\n"); } // Memory layout (row-major order) printf("\nMemory layout (row-major):\n"); int *ptr = &matrix[0][0]; for (int i = 0; i < 12; i++) { printf("%d ", ptr[i]); } printf("\n"); return 0; }

3D Arrays

#include <stdio.h> int main() { // 3D array (2 layers, 3 rows, 4 columns) int cube[2][3][4] = { { {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12} }, { {13, 14, 15, 16}, {17, 18, 19, 20}, {21, 22, 23, 24} } }; // Accessing elements printf("cube[1][2][3] = %d\n", cube[1][2][3]); // 24 // Traversing 3D array for (int i = 0; i < 2; i++) { printf("Layer %d:\n", i); for (int j = 0; j < 3; j++) { for (int k = 0; k < 4; k++) { printf("%4d", cube[i][j][k]); } printf("\n"); } printf("\n"); } return 0; }

Array of Strings

#include <stdio.h> int main() { // 2D character array (array of strings) char fruits[][10] = { "Apple", "Banana", "Cherry", "Date" }; int num_fruits = sizeof(fruits) / sizeof(fruits[0]); printf("Fruits:\n"); for (int i = 0; i < num_fruits; i++) { printf("%s\n", fruits[i]); } // Modify a string fruits[1][0] = 'b'; // Change 'B' to 'b' printf("\nModified: %s\n", fruits[1]); // "banana" return 0; }

Arrays and Pointers

Relationship Between Arrays and Pointers

#include <stdio.h> int main() { int arr[5] = {10, 20, 30, 40, 50}; // arr is a constant pointer to arr[0] int *ptr = arr; // ptr points to arr[0] printf("arr[0] address: %p\n", (void*)&arr[0]); printf("arr address: %p\n", (void*)arr); printf("ptr points to: %p\n", (void*)ptr); // Array indexing vs pointer arithmetic printf("\nArray indexing:\n"); for (int i = 0; i < 5; i++) { printf("arr[%d] = %d\n", i, arr[i]); } printf("\nPointer arithmetic:\n"); for (int i = 0; i < 5; i++) { printf("*(ptr + %d) = %d\n", i, *(ptr + i)); } // Using pointer as array name printf("\nptr[2] = %d\n", ptr[2]); // Same as arr[2] return 0; }

Pointer to Array

#include <stdio.h> int main() { int arr[5] = {10, 20, 30, 40, 50}; // Pointer to entire array (not just first element) int (*ptr_to_array)[5] = &arr; // Access through pointer to array printf("(*ptr_to_array)[2] = %d\n", (*ptr_to_array)[2]); // 30 // Difference between array pointer and element pointer int *ptr_to_element = arr; printf("ptr_to_element + 1: %p\n", (void*)(ptr_to_element + 1)); printf("ptr_to_array + 1: %p\n", (void*)(ptr_to_array + 1)); // ptr_to_array + 1 skips entire array (20 bytes) return 0; }

Passing Arrays to Functions

Method 1: Pass by Reference with Size

#include <stdio.h> // Function that receives array as pointer void print_array(int *arr, int size) { for (int i = 0; i < size; i++) { printf("%d ", arr[i]); } printf("\n"); } // Function that modifies array void double_elements(int arr[], int size) { for (int i = 0; i < size; i++) { arr[i] *= 2; } } int main() { int numbers[] = {1, 2, 3, 4, 5}; int size = sizeof(numbers) / sizeof(numbers[0]); printf("Original: "); print_array(numbers, size); double_elements(numbers, size); printf("Doubled: "); print_array(numbers, size); return 0; }

Method 2: Pass 2D Arrays

#include <stdio.h> // Must specify column size for 2D arrays void print_matrix(int matrix[][4], int rows) { for (int i = 0; i < rows; i++) { for (int j = 0; j < 4; j++) { printf("%4d", matrix[i][j]); } printf("\n"); } } // Alternative: pass as pointer to array void print_matrix2(int (*matrix)[4], int rows) { for (int i = 0; i < rows; i++) { for (int j = 0; j < 4; j++) { printf("%4d", matrix[i][j]); } printf("\n"); } } int main() { int matrix[3][4] = { {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12} }; printf("Matrix:\n"); print_matrix(matrix, 3); printf("\nUsing pointer syntax:\n"); print_matrix2(matrix, 3); return 0; }

Method 3: Returning Arrays from Functions

#include <stdio.h> #include <stdlib.h> // Return dynamically allocated array int* create_array(int size, int initial_value) { int *arr = (int*)malloc(size * sizeof(int)); if (arr == NULL) { return NULL; } for (int i = 0; i < size; i++) { arr[i] = initial_value; } return arr; } // Return static array (BAD - returns pointer to local variable) int* bad_function() { int local_arr[5] = {1, 2, 3, 4, 5}; return local_arr; // WRONG! local_arr goes out of scope } // Return static array (OK - static storage duration) int* static_array() { static int arr[5] = {10, 20, 30, 40, 50}; return arr; // OK - static persists } int main() { int *dynamic = create_array(10, 42); if (dynamic != NULL) { printf("First element: %d\n", dynamic[0]); free(dynamic); // Don't forget to free! } int *static_arr = static_array(); printf("Static array[2]: %d\n", static_arr[2]); // 30 return 0; }

Array of Pointers

Basic Array of Pointers

#include <stdio.h> #include <stdlib.h> int main() { int a = 10, b = 20, c = 30, d = 40; // Array of integer pointers int *ptr_array[4]; ptr_array[0] = &a; ptr_array[1] = &b; ptr_array[2] = &c; ptr_array[3] = &d; // Access values through pointer array for (int i = 0; i < 4; i++) { printf("*ptr_array[%d] = %d\n", i, *ptr_array[i]); } // Modify through pointer array *ptr_array[2] = 300; printf("c after modification: %d\n", c); // 300 return 0; }

Array of Strings (Using Pointers)

#include <stdio.h> int main() { // Array of pointers to string literals const char *colors[] = { "Red", "Green", "Blue", "Yellow" }; int num_colors = sizeof(colors) / sizeof(colors[0]); printf("Colors:\n"); for (int i = 0; i < num_colors; i++) { printf("%s\n", colors[i]); } // Note: String literals are read-only // colors[0][0] = 'R'; // Would cause undefined behavior return 0; }

Jagged Arrays (Rows of Different Lengths)

#include <stdio.h> #include <stdlib.h> int main() { // Jagged array using array of pointers int *jagged[3]; int sizes[3] = {3, 5, 2}; // Allocate rows of different sizes for (int i = 0; i < 3; i++) { jagged[i] = (int*)malloc(sizes[i] * sizeof(int)); // Initialize for (int j = 0; j < sizes[i]; j++) { jagged[i][j] = (i + 1) * (j + 1); } } // Print jagged array for (int i = 0; i < 3; i++) { printf("Row %d (size %d): ", i, sizes[i]); for (int j = 0; j < sizes[i]; j++) { printf("%d ", jagged[i][j]); } printf("\n"); } // Free memory for (int i = 0; i < 3; i++) { free(jagged[i]); } return 0; }

Common Array Operations

1. Linear Search

#include <stdio.h> int linear_search(int arr[], int size, int target) { for (int i = 0; i < size; i++) { if (arr[i] == target) { return i; // Return index if found } } return -1; // Not found } int main() { int numbers[] = {34, 12, 78, 45, 90, 23}; int size = sizeof(numbers) / sizeof(numbers[0]); int target = 45; int index = linear_search(numbers, size, target); if (index != -1) { printf("Found %d at index %d\n", target, index); } else { printf("%d not found\n", target); } return 0; }

2. Binary Search (Sorted Array)

#include <stdio.h> int binary_search(int arr[], int size, int target) { int left = 0, right = size - 1; while (left <= right) { int mid = left + (right - left) / 2; if (arr[mid] == target) { return mid; } if (arr[mid] < target) { left = mid + 1; } else { right = mid - 1; } } return -1; } int main() { int numbers[] = {12, 23, 34, 45, 78, 90}; // Must be sorted int size = sizeof(numbers) / sizeof(numbers[0]); int target = 34; int index = binary_search(numbers, size, target); if (index != -1) { printf("Found %d at index %d\n", target, index); } else { printf("%d not found\n", target); } return 0; }

3. Array Sorting (Bubble Sort)

#include <stdio.h> #include <stdbool.h> void bubble_sort(int arr[], int size) { for (int i = 0; i < size - 1; i++) { bool swapped = false; for (int j = 0; j < size - i - 1; j++) { if (arr[j] > arr[j + 1]) { // Swap elements int temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; swapped = true; } } if (!swapped) { break; // Array already sorted } } } void print_array(int arr[], int size) { for (int i = 0; i < size; i++) { printf("%d ", arr[i]); } printf("\n"); } int main() { int numbers[] = {64, 34, 25, 12, 22, 11, 90}; int size = sizeof(numbers) / sizeof(numbers[0]); printf("Original: "); print_array(numbers, size); bubble_sort(numbers, size); printf("Sorted: "); print_array(numbers, size); return 0; }

4. Array Reversal

#include <stdio.h> void reverse_array(int arr[], int size) { int left = 0, right = size - 1; while (left < right) { // Swap elements int temp = arr[left]; arr[left] = arr[right]; arr[right] = temp; left++; right--; } } int main() { int numbers[] = {1, 2, 3, 4, 5, 6, 7}; int size = sizeof(numbers) / sizeof(numbers[0]); printf("Original: "); for (int i = 0; i < size; i++) printf("%d ", numbers[i]); printf("\n"); reverse_array(numbers, size); printf("Reversed: "); for (int i = 0; i < size; i++) printf("%d ", numbers[i]); printf("\n"); return 0; }

5. Finding Duplicates

#include <stdio.h> #include <stdbool.h> void find_duplicates(int arr[], int size) { bool found_duplicate = false; for (int i = 0; i < size - 1; i++) { for (int j = i + 1; j < size; j++) { if (arr[i] == arr[j]) { printf("Duplicate found: %d at indices %d and %d\n", arr[i], i, j); found_duplicate = true; break; } } } if (!found_duplicate) { printf("No duplicates found\n"); } } int main() { int numbers1[] = {1, 2, 3, 4, 5, 3, 6, 7}; int size1 = sizeof(numbers1) / sizeof(numbers1[0]); printf("Array 1:\n"); find_duplicates(numbers1, size1); int numbers2[] = {1, 2, 3, 4, 5, 6, 7}; int size2 = sizeof(numbers2) / sizeof(numbers2[0]); printf("\nArray 2:\n"); find_duplicates(numbers2, size2); return 0; }

6. Array Rotation

#include <stdio.h> // Rotate array left by k positions void rotate_left(int arr[], int size, int k) { k = k % size; // Handle k >= size // Create temporary array for first k elements int temp[k]; for (int i = 0; i < k; i++) { temp[i] = arr[i]; } // Shift remaining elements left for (int i = 0; i < size - k; i++) { arr[i] = arr[i + k]; } // Copy back temp elements for (int i = 0; i < k; i++) { arr[size - k + i] = temp[i]; } } void print_array(int arr[], int size) { for (int i = 0; i < size; i++) { printf("%d ", arr[i]); } printf("\n"); } int main() { int numbers[] = {1, 2, 3, 4, 5, 6, 7}; int size = sizeof(numbers) / sizeof(numbers[0]); printf("Original: "); print_array(numbers, size); rotate_left(numbers, size, 3); printf("Rotated: "); print_array(numbers, size); return 0; }

7. Array Intersection and Union

#include <stdio.h> #include <stdbool.h> void find_intersection(int arr1[], int size1, int arr2[], int size2) { printf("Intersection: "); for (int i = 0; i < size1; i++) { for (int j = 0; j < size2; j++) { if (arr1[i] == arr2[j]) { printf("%d ", arr1[i]); break; } } } printf("\n"); } void find_union(int arr1[], int size1, int arr2[], int size2) { // This is a simple approach (assumes no duplicates within arrays) int union_size = size1 + size2; int union_arr[union_size]; int index = 0; // Copy first array for (int i = 0; i < size1; i++) { union_arr[index++] = arr1[i]; } // Add elements from second array that aren't in first for (int i = 0; i < size2; i++) { bool found = false; for (int j = 0; j < size1; j++) { if (arr2[i] == arr1[j]) { found = true; break; } } if (!found) { union_arr[index++] = arr2[i]; } } printf("Union: "); for (int i = 0; i < index; i++) { printf("%d ", union_arr[i]); } printf("\n"); } int main() { int arr1[] = {1, 3, 4, 5, 7}; int arr2[] = {2, 3, 5, 6}; int size1 = sizeof(arr1) / sizeof(arr1[0]); int size2 = sizeof(arr2) / sizeof(arr2[0]); find_intersection(arr1, size1, arr2, size2); find_union(arr1, size1, arr2, size2); return 0; }

Variable Length Arrays (C99)

VLA allows array size to be determined at runtime.

Basic VLA Usage

#include <stdio.h> void process_vla(int n) { // VLA - size determined at runtime int vla[n]; // Initialize for (int i = 0; i < n; i++) { vla[i] = i * i; } // Print for (int i = 0; i < n; i++) { printf("%d ", vla[i]); } printf("\n"); } int main() { int size; printf("Enter array size: "); scanf("%d", &size); process_vla(size); // Works with runtime size return 0; }

2D VLA

#include <stdio.h> // Function with VLA parameters void print_matrix(int rows, int cols, int matrix[rows][cols]) { for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { printf("%4d", matrix[i][j]); } printf("\n"); } } int main() { int rows = 3, cols = 4; // 2D VLA int matrix[rows][cols]; // Initialize int counter = 1; for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { matrix[i][j] = counter++; } } print_matrix(rows, cols, matrix); return 0; }

VLA Limitations

// VLAs cannot be: // - Static or global // - Initialized at declaration (except with = {0}) // - Have static storage duration // static int vla[n]; // ERROR: static can't be VLA // int vla2[n] = {1,2,3}; // ERROR: can't initialize VLA // But can do: int vla[n]; for (int i = 0; i < n; i++) vla[i] = 0; // Manual initialization

Array Limitations and Pitfalls

1. Array Index Out of Bounds

#include <stdio.h> int main() { int arr[5] = {10, 20, 30, 40, 50}; // No bounds checking in C! arr[5] = 60; // Buffer overflow - undefined behavior arr[-1] = 5; // Also possible - undefined behavior printf("arr[5] = %d\n", arr[5]); // May crash or print garbage return 0; }

2. Array Decay to Pointer

#include <stdio.h> void print_size(int arr[]) { printf("In function: sizeof(arr) = %zu\n", sizeof(arr)); // 8 (pointer size) } int main() { int arr[10]; printf("In main: sizeof(arr) = %zu\n", sizeof(arr)); // 40 (10 * 4) print_size(arr); return 0; }

3. Returning Local Arrays

#include <stdio.h> int* bad_function() { int local_array[5] = {1, 2, 3, 4, 5}; return local_array; // WRONG! local_array goes out of scope } int* good_function() { static int static_array[5] = {1, 2, 3, 4, 5}; return static_array; // OK - static persists } int main() { int *ptr = good_function(); // OK printf("%d\n", ptr[2]); // 3 // ptr = bad_function(); // Undefined behavior // printf("%d\n", ptr[2]); // May crash or print garbage return 0; }

4. No Built-in Copy or Compare

#include <stdio.h> #include <string.h> // For memcpy int main() { int arr1[5] = {1, 2, 3, 4, 5}; int arr2[5]; // arr2 = arr1; // ERROR: can't assign arrays // Must copy element by element for (int i = 0; i < 5; i++) { arr2[i] = arr1[i]; } // Or use memcpy memcpy(arr2, arr1, sizeof(arr1)); // Compare arrays int equal = 1; for (int i = 0; i < 5; i++) { if (arr1[i] != arr2[i]) { equal = 0; break; } } // Or use memcmp equal = memcmp(arr1, arr2, sizeof(arr1)) == 0; return 0; }

Best Practices

1. Always Check Array Bounds

#include <stdio.h> #include <assert.h> void safe_set(int arr[], int size, int index, int value) { assert(index >= 0 && index < size); // Debug check if (index >= 0 && index < size) { // Runtime check arr[index] = value; } } int main() { int numbers[10]; safe_set(numbers, 10, 5, 42); // OK safe_set(numbers, 10, 15, 42); // Caught by assert return 0; }

2. Use Named Constants for Array Sizes

#define MAX_STUDENTS 100 #define NAME_LENGTH 50 int student_ids[MAX_STUDENTS]; char student_names[MAX_STUDENTS][NAME_LENGTH]; // Better than magic numbers // int student_ids[100]; // char student_names[100][50];

3. Pass Size with Arrays

// GOOD: Pass size explicitly void process_array(int arr[], size_t size) { for (size_t i = 0; i < size; i++) { // process arr[i] } } // BAD: Relying on sentinel or global void process_array_bad(int arr[]) { // Can't know size without additional information }

4. Initialize Arrays

// GOOD int arr[10] = {0}; // All elements zero int arr2[] = {1, 2, 3, 4, 5}; // Compiler counts elements // BAD int arr3[10]; // Contains garbage values

5. Use sizeof for Portability

// GOOD int arr[20]; for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++) { arr[i] = i; } // BAD for (int i = 0; i < 20; i++) { // Hard-coded size arr[i] = i; }

6. Be Careful with String Arrays

#include <string.h> char name[20] = "John"; // Room for "John" plus null terminator // char name2[4] = "John"; // ERROR: no room for null terminator strcpy(name, "Christopher"); // Safe: 20 > 11 + 1 // strcpy(name, "Christopher Alexandros"); // Unsafe: would overflow

7. Consider Using Dynamic Allocation for Large Arrays

#include <stdlib.h> // For large arrays or variable size int *large_array = malloc(1000000 * sizeof(int)); if (large_array != NULL) { // Use array free(large_array); // Don't forget to free }

8. Document Array Assumptions

/** * Finds maximum value in array * @param arr Array of integers * @param size Number of elements (must be > 0) * @return Maximum value */ int find_max(int arr[], size_t size) { // Implementation }

Summary Table

OperationSyntaxExample
Declarationtype name[size];int scores[10];
Initializationtype name[] = {vals};int nums[] = {1,2,3};
Accessname[index]scores[5] = 95;
Size calculationsizeof(arr)/sizeof(arr[0])int size = sizeof(nums)/sizeof(nums[0]);
2D declarationtype name[rows][cols];int matrix[3][4];
2D accessname[row][col]matrix[1][2] = 42;
Pass to functionfunc(arr, size);print_array(nums, 5);
Dynamic arraymalloc(size * sizeof(type))int *arr = malloc(n * sizeof(int));

Common Array Patterns Cheat Sheet

// 1. Traverse array for (int i = 0; i < size; i++) { // process array[i] } // 2. Find maximum/minimum int max = arr[0]; for (int i = 1; i < size; i++) { if (arr[i] > max) max = arr[i]; } // 3. Calculate sum int sum = 0; for (int i = 0; i < size; i++) { sum += arr[i]; } // 4. Copy array int dest[size]; for (int i = 0; i < size; i++) { dest[i] = src[i]; } // 5. Reverse array for (int i = 0; i < size/2; i++) { int temp = arr[i]; arr[i] = arr[size-1-i]; arr[size-1-i] = temp; } // 6. Search for value int found = -1; for (int i = 0; i < size; i++) { if (arr[i] == target) { found = i; break; } } // 7. 2D array traversal for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { // process matrix[i][j] } }

Conclusion

Arrays are a fundamental data structure in C that every programmer must master. Key takeaways:

  • Arrays store multiple elements of the same type contiguously
  • Access is via zero-based indices
  • No bounds checking - programmer must ensure safety
  • Array names decay to pointers in most contexts
  • Size must be known to avoid buffer overflows
  • Multidimensional arrays are arrays of arrays
  • VLAs provide runtime sizing (C99)
  • Arrays and pointers are closely related but not identical

Understanding arrays thoroughly is essential for effective C programming, as they form the basis for strings, matrices, and many other data structures.

Complete C Programming Guide + Compilers Collection


1. C srand() Function – Understanding Seed Initialization

https://macronepal.com/understanding-the-c-srand-function
Explains how srand() initializes the pseudo-random number generator in C by setting a seed value. Using the same seed produces the same sequence, while time(NULL) gives different results each run.


2. C rand() Function Mechanics and Limitations

https://macronepal.com/c-rand-function-mechanics-and-limitations
Explains how rand() generates pseudo-random numbers between 0 and RAND_MAX, its deterministic nature, and limitations for security use cases.


3. C log() Function

https://macronepal.com/c-log-function-2
Covers natural logarithm calculation using <math.h> and its applications.


4. Mastering Date and Time in C

https://macronepal.com/mastering-date-and-time-in-c
Explains <time.h> functions like time(), clock(), difftime(), and struct tm.


5. Mastering time_t Type in C

https://macronepal.com/mastering-the-c-time_t-type-for-time-management
Explains time representation as seconds since Unix epoch and conversion functions.


6. C exp() Function

https://macronepal.com/c-exp-function-mechanics-and-implementation
Explains exponential function exp(x) and its scientific applications.


7. C log() Function (Alternate Guide)

https://macronepal.com/c-log-function
Comparison of log() and log10() with usage examples.


8. C log10() Function

https://macronepal.com/mastering-the-log10-function-in-c
Explains base-10 logarithm for engineering and scientific applications.


9. C tan() Function

https://macronepal.com/understanding-the-c-tan-function
Explains tangent function and radian-based calculations.


10. Random Numbers in C (Secure vs Predictable)

https://macronepal.com/mastering-c-random-numbers-for-secure-and-predictable-applications
Explains difference between rand() and secure randomness methods.


11. Free Online C Compiler

https://macronepal.com/free-online-c-code-compiler-2
Browser-based compiler for testing C programs instantly.


C Functions, Arguments, Parameters & Flow

Mastering Functions in C – Complete Guide

https://macronepal.com/c/mastering-functions-in-c-a-complete-guide/
Covers function structure, modular programming, and real-world usage.


Function Arguments in C

https://macronepal.com/c-function-arguments/
Explains how arguments are passed and used in function calls.


Function Parameters in C

https://macronepal.com/c-function-parameters/
Explains defining inputs for functions and matching them with arguments.


Function Declarations in C

https://macronepal.com/c-function-declarations-syntax-rules-and-best-practices/
Covers prototypes, syntax rules, and best practices.


Function Calls in C

https://macronepal.com/understanding-function-calls-in-c-syntax-mechanics-and-best-practices/
Explains execution flow and parameter handling during function calls.


Void Functions in C

https://macronepal.com/understanding-void-functions-in-c-syntax-patterns-and-best-practices/
Explains functions that do not return values.


Return Values in C

https://macronepal.com/c-return-values-mechanics-types-and-best-practices/
Explains different return types and how functions return results.


Pass-by-Value in C

https://macronepal.com/aws/understanding-pass-by-value-in-c-mechanics-implications-and-best-practices/
Explains how copies of variables are passed into functions.


Pass-by-Reference in C

https://macronepal.com/c/understanding-pass-by-reference-in-c-pointers-semantics-and-safe-practices/
Explains using pointers to modify original variables.


C strstr() Function

https://macronepal.com/aws/c-strstr-function/
Explains substring search inside strings in C.


C Preprocessor & Macros

https://macronepal.com/mastering-c-variadic-macros-for-flexible-debugging/
https://macronepal.com/mastering-the-stdc-macro-in-c/
https://macronepal.com/c-time-macro-mechanics-and-usage/
https://macronepal.com/understanding-the-c-date-macro/
https://macronepal.com/c-file-type/
https://macronepal.com/mastering-c-line-macro-for-debugging-and-diagnostics/
https://macronepal.com/mastering-predefined-macros-in-c/
https://macronepal.com/c-error-directive-mechanics-and-usage/
https://macronepal.com/understanding-the-c-pragma-directive/
https://macronepal.com/c-include-directive/


C Structures, Memory, Scope & Linkage

https://macronepal.com/mastering-structures-in-c/
https://macronepal.com/c-structure-declaration-mechanics-and-usage/
https://macronepal.com/c-structure-initialization-mechanics-and-best-practices/
https://macronepal.com/mastering-c-structure-member-access-for-reliable-data-handling/
https://macronepal.com/c-nested-structures/
https://macronepal.com/mastering-arrays-of-structures-in-c/
https://macronepal.com/c-structure-pointers-mechanics-and-implementation/
https://macronepal.com/understanding-c-structure-parameter-passing-mechanics/
https://macronepal.com/mastering-c-returning-structures-for-efficient-data-flow/
https://macronepal.com/c-self-referential-structures/
https://macronepal.com/mastering-structure-alignment-in-c/
https://macronepal.com/c-structure-padding-mechanics-and-optimization/
https://macronepal.com/understanding-c-flexible-array-members-mechanics-and-usage/
https://macronepal.com/mastering-c-anonymous-structures-for-flattened-data-layouts/
https://macronepal.com/c-unions/
https://macronepal.com/mastering-c-name-mangling-and-symbol-decoration/
https://macronepal.com/c-no-linkage-mechanics-and-scope-isolation/
https://macronepal.com/understanding-c-internal-linkage-mechanics-and-architecture/


C Scope, Storage Classes & Typedef

https://macronepal.com/mastering-function-prototype-scope-in-c/
https://macronepal.com/c-function-scope-mechanics-and-visibility/
https://macronepal.com/understanding-c-file-scope-mechanics-and-architecture/
https://macronepal.com/mastering-c-scope-rules-for-predictable-name-resolution/
https://macronepal.com/c-scope-rules/
https://macronepal.com/mastering-c-register-storage-class-for-historical-context-and-modern-alternatives/
https://macronepal.com/mastering-_thread_local-in-c/
https://macronepal.com/c-extern-storage-class-mechanics-and-usage/
https://macronepal.com/understanding-the-c-static-storage-class-mechanics-and-usage/
https://macronepal.com/c-auto-storage-class/
https://macronepal.com/c-typedef-with-pointers/


Extra Articles

https://macronepal.com/13757-2/
https://macronepal.com/13748-2/
https://macronepal.com/13747-2/
https://macronepal.com/13746-2/
https://macronepal.com/13745-2/
https://macronepal.com/13708-2/
https://macronepal.com/13707-2/
https://macronepal.com/13702-2/


Online Compilers

https://macronepal.com/free-html-online-code-compiler/
https://macronepal.com/free-online-python-code-compiler/
https://macronepal.com/free-online-python2-code-compiler/
https://macronepal.com/free-online-java-code-compiler/
https://macronepal.com/free-online-javascript-code-compiler/
https://macronepal.com/free-online-node-js-code-compiler/
https://macronepal.com/free-online-c-code-compiler/
https://macronepal.com/free-online-c-code-compiler-2/
https://macronepal.com/free-online-c-code-compiler-3/
https://macronepal.com/free-online-php-code-compiler/
https://macronepal.com/free-online-ruby-code-compiler/
https://macronepal.com/free-online-perl-code-compiler/
https://macronepal.com/free-online-lua-code-compiler/
https://macronepal.com/free-online-tcl-code-compiler/
https://macronepal.com/free-online-groovy-code-compiler/
https://macronepal.com/free-online-j-shell-code-compiler/
https://macronepal.com/free-online-haskell-code-compiler/
https://macronepal.com/free-online-scala-code-compiler/
https://macronepal.com/free-online-common-lisp-code-compiler/
https://macronepal.com/free-online-d-code-compiler/
https://macronepal.com/free-online-ada-code-compiler/
https://macronepal.com/free-erlang-code-compiler/
https://macronepal.com/free-online-assembly-code-compiler/

Leave a Reply

Your email address will not be published. Required fields are marked *


Macro Nepal Helper