Arrays are fundamental data structures in C, but passing them to functions requires understanding C's pointer semantics. Unlike simple variables, arrays are passed by reference—the function receives the memory address of the first element, not a copy of the entire array. This behavior has profound implications for efficiency, data modification, and programming style. For C developers, mastering array passing techniques is essential for writing efficient, correct, and maintainable code.
What Happens When You Pass an Array to a Function?
When you pass an array to a function in C, the array name "decays" to a pointer to its first element. The function receives this pointer, not a copy of the entire array. This means:
- No array copying - Efficient for large arrays
- Modifications affect the original - Changes made in the function persist
- Size information is lost - The function doesn't know the array length
Why Passing Arrays to Functions is Essential in C
- Code Reusability: Write generic functions that work with arrays of different sizes.
- Modularity: Break complex array operations into manageable functions.
- Efficiency: Avoid copying large amounts of data unnecessarily.
- Abstraction: Hide implementation details of array processing.
- Algorithm Implementation: Implement sorting, searching, and transformation algorithms.
Basic Array Passing Syntax
#include <stdio.h>
// Different ways to declare array parameters
// Method 1: As an array (most readable)
void printArray1(int arr[], int size) {
printf("Method 1 (arr[]): ");
for (int i = 0; i < size; i++) {
printf("%d ", arr[i]);
}
printf("\n");
}
// Method 2: As a pointer (more explicit)
void printArray2(int *arr, int size) {
printf("Method 2 (*arr): ");
for (int i = 0; i < size; i++) {
printf("%d ", *(arr + i)); // Pointer arithmetic
}
printf("\n");
}
// Method 3: With size specified (fixed size - less flexible)
void printArray3(int arr[5], int size) {
printf("Method 3 (arr[5]): ");
for (int i = 0; i < size && i < 5; i++) {
printf("%d ", arr[i]);
}
printf("\n");
}
int main() {
printf("=== Basic Array Passing ===\n\n");
int numbers[] = {10, 20, 30, 40, 50};
int size = sizeof(numbers) / sizeof(numbers[0]);
printf("Original array: ");
for (int i = 0; i < size; i++) {
printf("%d ", numbers[i]);
}
printf("\n\n");
// All three methods work
printArray1(numbers, size);
printArray2(numbers, size);
printArray3(numbers, size);
// Prove that arr[] and *arr are equivalent in parameters
printf("\nAll methods receive the same address: %p\n", (void*)numbers);
return 0;
}
Passing Arrays by Reference vs Value
#include <stdio.h>
// Array is passed by reference (pointer) - modifications affect original
void modifyArray(int arr[], int size) {
printf(" Inside modifyArray: address = %p\n", (void*)arr);
for (int i = 0; i < size; i++) {
arr[i] = arr[i] * 2; // Modifies original
}
}
// Integer is passed by value - modifications don't affect original
void modifyValue(int x) {
printf(" Inside modifyValue: address = %p\n", (void*)&x);
x = x * 2; // Modifies copy only
printf(" Inside modifyValue: x = %d\n", x);
}
int main() {
printf("=== Pass by Reference vs Value ===\n\n");
int numbers[] = {1, 2, 3, 4, 5};
int size = sizeof(numbers) / sizeof(numbers[0]);
int value = 10;
printf("Before array modification: ");
for (int i = 0; i < size; i++) printf("%d ", numbers[i]);
printf("\n");
printf("Array address in main: %p\n", (void*)numbers);
modifyArray(numbers, size);
printf("After array modification: ");
for (int i = 0; i < size; i++) printf("%d ", numbers[i]);
printf("\n\n");
printf("Before value modification: value = %d\n", value);
printf("Value address in main: %p\n", (void*)&value);
modifyValue(value);
printf("After value modification: value = %d\n", value);
printf("\nKey insight: Arrays are ALWAYS passed by reference,\n");
printf(" scalars are passed by value.\n");
return 0;
}
Passing Different Array Types
#include <stdio.h>
#include <string.h>
// Integer arrays
void processInts(int arr[], int size) {
int sum = 0;
for (int i = 0; i < size; i++) {
sum += arr[i];
}
printf(" Sum: %d, Average: %.2f\n", sum, (float)sum / size);
}
// Double arrays
void processDoubles(double arr[], int size) {
double sum = 0.0;
for (int i = 0; i < size; i++) {
sum += arr[i];
}
printf(" Sum: %.2f, Average: %.2f\n", sum, sum / size);
}
// Character arrays (strings)
void processString(char str[]) {
printf(" String: \"%s\", Length: %zu\n", str, strlen(str));
// Convert to uppercase
for (int i = 0; str[i]; i++) {
if (str[i] >= 'a' && str[i] <= 'z') {
str[i] = str[i] - 32; // Modifies original
}
}
}
// Multi-dimensional arrays (must specify all but first dimension)
void process2DArray(int arr[][3], int rows) {
printf(" 2D Array (%d x 3):\n", rows);
for (int i = 0; i < rows; i++) {
printf(" Row %d: ", i);
for (int j = 0; j < 3; j++) {
printf("%d ", arr[i][j]);
}
printf("\n");
}
}
// Array of pointers (e.g., array of strings)
void processStringArray(char *arr[], int size) {
printf(" String array (%d elements):\n", size);
for (int i = 0; i < size; i++) {
printf(" [%d]: \"%s\"\n", i, arr[i]);
}
}
int main() {
printf("=== Passing Different Array Types ===\n\n");
int intArray[] = {1, 2, 3, 4, 5, 6};
processInts(intArray, 6);
double doubleArray[] = {1.5, 2.5, 3.5, 4.5};
processDoubles(doubleArray, 4);
char str[] = "hello world";
printf("\nOriginal string: \"%s\"\n", str);
processString(str);
printf("After function: \"%s\"\n", str);
int matrix[][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
printf("\n");
process2DArray(matrix, 3);
char *fruits[] = {"apple", "banana", "cherry", "date"};
printf("\n");
processStringArray(fruits, 4);
return 0;
}
Passing Array Slices
#include <stdio.h>
// Process only part of an array by passing pointer to starting element
void processSlice(int *start, int count) {
printf(" Processing slice of %d elements: ", count);
for (int i = 0; i < count; i++) {
printf("%d ", start[i]);
}
printf("\n");
}
// Process every nth element
void processEveryNth(int arr[], int size, int n) {
printf(" Every %dth element: ", n);
for (int i = 0; i < size; i += n) {
printf("%d ", arr[i]);
}
printf("\n");
}
// Process a subarray
void processSubarray(int arr[], int start, int end) {
printf(" Subarray [%d:%d]: ", start, end);
for (int i = start; i <= end; i++) {
printf("%d ", arr[i]);
}
printf("\n");
}
int main() {
printf("=== Array Slices ===\n\n");
int numbers[] = {10, 20, 30, 40, 50, 60, 70, 80, 90, 100};
int size = sizeof(numbers) / sizeof(numbers[0]);
printf("Full array: ");
for (int i = 0; i < size; i++) printf("%d ", numbers[i]);
printf("\n\n");
// Pass slices by pointing to different starting positions
processSlice(numbers, 5); // First 5 elements
processSlice(numbers + 5, 3); // Elements 5-7 (0-based)
processSlice(&numbers[2], 4); // Elements 2-5
printf("\n");
processEveryNth(numbers, size, 3);
printf("\n");
processSubarray(numbers, 3, 7);
return 0;
}
Modifying Arrays in Functions
#include <stdio.h>
// Fill array with values
void fillArray(int arr[], int size, int value) {
for (int i = 0; i < size; i++) {
arr[i] = value;
}
}
// Reverse array in place
void reverseArray(int arr[], int size) {
for (int i = 0; i < size / 2; i++) {
int temp = arr[i];
arr[i] = arr[size - 1 - i];
arr[size - 1 - i] = temp;
}
}
// Scale array elements
void scaleArray(int arr[], int size, int factor) {
for (int i = 0; i < size; i++) {
arr[i] *= factor;
}
}
// Remove duplicates (modifies array, returns new size)
int removeDuplicates(int arr[], int size) {
if (size <= 1) return size;
int newSize = 1;
for (int i = 1; i < size; i++) {
if (arr[i] != arr[newSize - 1]) {
arr[newSize] = arr[i];
newSize++;
}
}
return newSize;
}
// Shift array elements left
void shiftLeft(int arr[], int size, int positions) {
positions = positions % size;
if (positions == 0) return;
// Simple but inefficient - for demonstration
for (int p = 0; p < positions; p++) {
int first = arr[0];
for (int i = 0; i < size - 1; i++) {
arr[i] = arr[i + 1];
}
arr[size - 1] = first;
}
}
void printArray(int arr[], int size, const char *title) {
printf("%s: [", title);
for (int i = 0; i < size; i++) {
printf("%d", arr[i]);
if (i < size - 1) printf(", ");
}
printf("]\n");
}
int main() {
printf("=== Modifying Arrays in Functions ===\n\n");
int numbers[10];
int size = 10;
fillArray(numbers, size, 5);
printArray(numbers, size, "After fill with 5");
scaleArray(numbers, size, 2);
printArray(numbers, size, "After scale by 2");
reverseArray(numbers, size);
printArray(numbers, size, "After reverse");
printf("\n");
int data[] = {1, 1, 2, 2, 2, 3, 4, 4, 5, 5, 5, 5};
int dataSize = sizeof(data) / sizeof(data[0]);
printArray(data, dataSize, "Original with duplicates");
int newSize = removeDuplicates(data, dataSize);
printArray(data, newSize, "After removing duplicates");
printf("\n");
int rotate[] = {1, 2, 3, 4, 5, 6, 7, 8};
int rotateSize = sizeof(rotate) / sizeof(rotate[0]);
printArray(rotate, rotateSize, "Before rotation");
shiftLeft(rotate, rotateSize, 3);
printArray(rotate, rotateSize, "After left shift 3");
return 0;
}
Searching and Finding in Arrays
#include <stdio.h>
#include <stdbool.h>
// Linear search - returns index or -1
int linearSearch(int arr[], int size, int target) {
for (int i = 0; i < size; i++) {
if (arr[i] == target) {
return i;
}
}
return -1;
}
// Binary search (array must be sorted)
int binarySearch(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;
}
// Find maximum element
int findMax(int arr[], int size) {
if (size <= 0) return 0; // Error case
int max = arr[0];
for (int i = 1; i < size; i++) {
if (arr[i] > max) {
max = arr[i];
}
}
return max;
}
// Find minimum element
int findMin(int arr[], int size) {
if (size <= 0) return 0; // Error case
int min = arr[0];
for (int i = 1; i < size; i++) {
if (arr[i] < min) {
min = arr[i];
}
}
return min;
}
// Find all occurrences (returns count, stores indices in result array)
int findAllOccurrences(int arr[], int size, int target, int indices[]) {
int count = 0;
for (int i = 0; i < size; i++) {
if (arr[i] == target) {
indices[count++] = i;
}
}
return count;
}
// Find first and last occurrence (for sorted arrays)
void findFirstLast(int arr[], int size, int target, int *first, int *last) {
*first = -1;
*last = -1;
for (int i = 0; i < size; i++) {
if (arr[i] == target) {
if (*first == -1) *first = i;
*last = i;
}
}
}
int main() {
printf("=== Searching in Arrays ===\n\n");
int numbers[] = {10, 23, 45, 67, 89, 23, 12, 23, 90, 23};
int size = sizeof(numbers) / sizeof(numbers[0]);
printf("Array: ");
for (int i = 0; i < size; i++) printf("%d ", numbers[i]);
printf("\n\n");
// Linear search
int target = 23;
int pos = linearSearch(numbers, size, target);
printf("Linear search for %d: found at index %d\n", target, pos);
// Find all occurrences
int indices[10];
int count = findAllOccurrences(numbers, size, target, indices);
printf("All occurrences of %d at indices: ", target);
for (int i = 0; i < count; i++) {
printf("%d ", indices[i]);
}
printf("\n");
// Min and max
printf("Maximum: %d\n", findMax(numbers, size));
printf("Minimum: %d\n", findMin(numbers, size));
// Binary search (needs sorted array)
printf("\nBinary search (requires sorted array):\n");
int sorted[] = {10, 20, 30, 40, 50, 60, 70, 80, 90};
int sortedSize = sizeof(sorted) / sizeof(sorted[0]);
printf("Sorted array: ");
for (int i = 0; i < sortedSize; i++) printf("%d ", sorted[i]);
printf("\n");
pos = binarySearch(sorted, sortedSize, 50);
printf("Binary search for 50: found at index %d\n", pos);
// First and last occurrence
int first, last;
findFirstLast(sorted, sortedSize, 50, &first, &last);
printf("First occurrence of 50: %d, Last: %d\n", first, last);
return 0;
}
Sorting Arrays
#include <stdio.h>
#include <stdbool.h>
// Bubble sort
void bubbleSort(int arr[], int size) {
for (int i = 0; i < size - 1; i++) {
bool swapped = false;
for (int j = 0; j < size - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
swapped = true;
}
}
if (!swapped) break; // Already sorted
}
}
// Selection sort
void selectionSort(int arr[], int size) {
for (int i = 0; i < size - 1; i++) {
int minIdx = i;
for (int j = i + 1; j < size; j++) {
if (arr[j] < arr[minIdx]) {
minIdx = j;
}
}
if (minIdx != i) {
int temp = arr[i];
arr[i] = arr[minIdx];
arr[minIdx] = temp;
}
}
}
// Insertion sort
void insertionSort(int arr[], int size) {
for (int i = 1; i < size; i++) {
int key = arr[i];
int j = i - 1;
while (j >= 0 && arr[j] > key) {
arr[j + 1] = arr[j];
j--;
}
arr[j + 1] = key;
}
}
// Merge helper for merge sort
void merge(int arr[], int left, int mid, int right) {
int n1 = mid - left + 1;
int n2 = right - mid;
int L[n1], R[n2];
for (int i = 0; i < n1; i++) L[i] = arr[left + i];
for (int j = 0; j < n2; j++) R[j] = arr[mid + 1 + j];
int i = 0, j = 0, k = left;
while (i < n1 && j < n2) {
if (L[i] <= R[j]) {
arr[k++] = L[i++];
} else {
arr[k++] = R[j++];
}
}
while (i < n1) arr[k++] = L[i++];
while (j < n2) arr[k++] = R[j++];
}
// Merge sort
void mergeSort(int arr[], int left, int right) {
if (left < right) {
int mid = left + (right - left) / 2;
mergeSort(arr, left, mid);
mergeSort(arr, mid + 1, right);
merge(arr, left, mid, right);
}
}
// Wrapper for merge sort
void mergeSortWrapper(int arr[], int size) {
mergeSort(arr, 0, size - 1);
}
void printArray(int arr[], int size, const char *title) {
printf("%s: [", title);
for (int i = 0; i < size; i++) {
printf("%d", arr[i]);
if (i < size - 1) printf(", ");
}
printf("]\n");
}
int main() {
printf("=== Sorting Arrays ===\n\n");
// Test each sorting algorithm
int test1[] = {64, 34, 25, 12, 22, 11, 90};
int size1 = sizeof(test1) / sizeof(test1[0]);
int test2[] = {64, 34, 25, 12, 22, 11, 90};
int size2 = sizeof(test2) / sizeof(test2[0]);
int test3[] = {64, 34, 25, 12, 22, 11, 90};
int size3 = sizeof(test3) / sizeof(test3[0]);
int test4[] = {64, 34, 25, 12, 22, 11, 90};
int size4 = sizeof(test4) / sizeof(test4[0]);
printArray(test1, size1, "Original");
bubbleSort(test1, size1);
printArray(test1, size1, "Bubble sort");
selectionSort(test2, size2);
printArray(test2, size2, "Selection sort");
insertionSort(test3, size3);
printArray(test3, size3, "Insertion sort");
mergeSortWrapper(test4, size4);
printArray(test4, size4, "Merge sort");
return 0;
}
Statistical Functions
#include <stdio.h>
#include <math.h>
// Calculate sum
int arraySum(int arr[], int size) {
int sum = 0;
for (int i = 0; i < size; i++) {
sum += arr[i];
}
return sum;
}
// Calculate mean (average)
double arrayMean(int arr[], int size) {
if (size == 0) return 0.0;
return (double)arraySum(arr, size) / size;
}
// Calculate median (array must be sorted first)
double arrayMedian(int arr[], int size) {
if (size == 0) return 0.0;
if (size % 2 == 1) {
return arr[size / 2];
} else {
return (arr[size / 2 - 1] + arr[size / 2]) / 2.0;
}
}
// Calculate mode (most frequent element)
int arrayMode(int arr[], int size) {
if (size <= 1) return size > 0 ? arr[0] : 0;
int maxCount = 0;
int mode = arr[0];
for (int i = 0; i < size; i++) {
int count = 0;
for (int j = 0; j < size; j++) {
if (arr[j] == arr[i]) count++;
}
if (count > maxCount) {
maxCount = count;
mode = arr[i];
}
}
return mode;
}
// Calculate variance
double arrayVariance(int arr[], int size) {
if (size <= 1) return 0.0;
double mean = arrayMean(arr, size);
double sum = 0.0;
for (int i = 0; i < size; i++) {
double diff = arr[i] - mean;
sum += diff * diff;
}
return sum / (size - 1); // Sample variance
}
// Calculate standard deviation
double arrayStdDev(int arr[], int size) {
return sqrt(arrayVariance(arr, size));
}
// Find range (max - min)
int arrayRange(int arr[], int size) {
if (size <= 1) return size > 0 ? 0 : -1;
int min = arr[0], max = arr[0];
for (int i = 1; i < size; i++) {
if (arr[i] < min) min = arr[i];
if (arr[i] > max) max = arr[i];
}
return max - min;
}
int main() {
printf("=== Statistical Functions ===\n\n");
int data[] = {5, 3, 8, 3, 9, 1, 6, 3, 7, 2};
int size = sizeof(data) / sizeof(data[0]);
printf("Data: ");
for (int i = 0; i < size; i++) printf("%d ", data[i]);
printf("\n\n");
printf("Sum: %d\n", arraySum(data, size));
printf("Mean: %.2f\n", arrayMean(data, size));
// Need sorted array for median
int sorted[size];
for (int i = 0; i < size; i++) sorted[i] = data[i];
insertionSort(sorted, size);
printf("Sorted: ");
for (int i = 0; i < size; i++) printf("%d ", sorted[i]);
printf("\n");
printf("Median: %.2f\n", arrayMedian(sorted, size));
printf("Mode: %d\n", arrayMode(data, size));
printf("Variance: %.2f\n", arrayVariance(data, size));
printf("Std Dev: %.2f\n", arrayStdDev(data, size));
printf("Range: %d\n", arrayRange(data, size));
return 0;
}
Multi-dimensional Arrays
#include <stdio.h>
// Passing 2D arrays - must specify all but first dimension
void printMatrix(int rows, int cols, int matrix[][cols]) {
printf("Matrix (%d x %d):\n", rows, cols);
for (int i = 0; i < rows; i++) {
printf(" Row %d: ", i);
for (int j = 0; j < cols; j++) {
printf("%4d ", matrix[i][j]);
}
printf("\n");
}
}
// Matrix addition
void addMatrices(int rows, int cols,
int a[][cols], int b[][cols], int result[][cols]) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
result[i][j] = a[i][j] + b[i][j];
}
}
}
// Matrix multiplication
void multiplyMatrices(int r1, int c1, int a[][c1],
int r2, int c2, int b[][c2],
int result[][c2]) {
if (c1 != r2) {
printf("Error: Incompatible dimensions for multiplication\n");
return;
}
// Initialize result to zero
for (int i = 0; i < r1; i++) {
for (int j = 0; j < c2; j++) {
result[i][j] = 0;
}
}
// Multiply
for (int i = 0; i < r1; i++) {
for (int j = 0; j < c2; j++) {
for (int k = 0; k < c1; k++) {
result[i][j] += a[i][k] * b[k][j];
}
}
}
}
// Find element in 2D array
int* findInMatrix(int rows, int cols, int matrix[][cols], int target) {
static int notFound[2] = {-1, -1};
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
if (matrix[i][j] == target) {
static int position[2];
position[0] = i;
position[1] = j;
return position;
}
}
}
return notFound;
}
// Sum of each row
void rowSums(int rows, int cols, int matrix[][cols], int sums[]) {
for (int i = 0; i < rows; i++) {
sums[i] = 0;
for (int j = 0; j < cols; j++) {
sums[i] += matrix[i][j];
}
}
}
// Sum of each column
void columnSums(int rows, int cols, int matrix[][cols], int sums[]) {
for (int j = 0; j < cols; j++) {
sums[j] = 0;
for (int i = 0; i < rows; i++) {
sums[j] += matrix[i][j];
}
}
}
int main() {
printf("=== Multi-dimensional Arrays ===\n\n");
int A[2][3] = {{1, 2, 3}, {4, 5, 6}};
int B[2][3] = {{7, 8, 9}, {10, 11, 12}};
int C[2][3];
int D[3][2] = {{1, 2}, {3, 4}, {5, 6}};
int E[2][2];
printf("Matrix A:\n");
printMatrix(2, 3, A);
printf("\nMatrix B:\n");
printMatrix(2, 3, B);
addMatrices(2, 3, A, B, C);
printf("\nA + B:\n");
printMatrix(2, 3, C);
printf("\nMatrix D:\n");
printMatrix(3, 2, D);
multiplyMatrices(2, 3, A, 3, 2, D, E);
printf("\nA * D:\n");
printMatrix(2, 2, E);
int *pos = findInMatrix(2, 3, A, 5);
printf("\nFind 5 in A: at [%d][%d]\n", pos[0], pos[1]);
int rowSum[2], colSum[3];
rowSums(2, 3, A, rowSum);
columnSums(2, 3, A, colSum);
printf("\nRow sums of A: %d, %d\n", rowSum[0], rowSum[1]);
printf("Column sums of A: %d, %d, %d\n", colSum[0], colSum[1], colSum[2]);
return 0;
}
Passing Arrays of Structures
#include <stdio.h>
#include <string.h>
typedef struct {
char name[50];
int age;
float salary;
} Employee;
// Print array of structures
void printEmployees(Employee emp[], int count) {
printf("Employee List:\n");
for (int i = 0; i < count; i++) {
printf(" [%d] %s, %d years old, $%.2f\n",
i + 1, emp[i].name, emp[i].age, emp[i].salary);
}
}
// Find employee by name
Employee* findEmployeeByName(Employee emp[], int count, const char* name) {
for (int i = 0; i < count; i++) {
if (strcmp(emp[i].name, name) == 0) {
return &emp[i];
}
}
return NULL;
}
// Sort employees by age
void sortEmployeesByAge(Employee emp[], int count) {
for (int i = 0; i < count - 1; i++) {
for (int j = 0; j < count - 1 - i; j++) {
if (emp[j].age > emp[j + 1].age) {
Employee temp = emp[j];
emp[j] = emp[j + 1];
emp[j + 1] = temp;
}
}
}
}
// Give raise to all employees
void giveRaise(Employee emp[], int count, float percentage) {
for (int i = 0; i < count; i++) {
emp[i].salary *= (1.0 + percentage / 100.0);
}
}
// Calculate average salary
float averageSalary(Employee emp[], int count) {
if (count == 0) return 0.0;
float total = 0.0;
for (int i = 0; i < count; i++) {
total += emp[i].salary;
}
return total / count;
}
// Filter employees by age threshold
int filterByAge(Employee emp[], int count, Employee result[], int minAge) {
int resultCount = 0;
for (int i = 0; i < count; i++) {
if (emp[i].age >= minAge) {
result[resultCount++] = emp[i];
}
}
return resultCount;
}
int main() {
printf("=== Arrays of Structures ===\n\n");
Employee company[] = {
{"Alice Johnson", 28, 65000.0},
{"Bob Smith", 35, 82000.0},
{"Charlie Brown", 42, 95000.0},
{"Diana Prince", 31, 71000.0},
{"Edward Norton", 29, 58000.0}
};
int count = sizeof(company) / sizeof(company[0]);
printEmployees(company, count);
printf("\nAverage salary: $%.2f\n", averageSalary(company, count));
printf("\nGiving 5%% raise...\n");
giveRaise(company, count, 5.0);
printEmployees(company, count);
printf("\nSorting by age...\n");
sortEmployeesByAge(company, count);
printEmployees(company, count);
Employee seniors[10];
int seniorCount = filterByAge(company, count, seniors, 35);
printf("\nEmployees age 35 or older:\n");
printEmployees(seniors, seniorCount);
Employee* found = findEmployeeByName(company, count, "Charlie Brown");
if (found) {
printf("\nFound: %s, age %d\n", found->name, found->age);
}
return 0;
}
Common Pitfalls and Best Practices
#include <stdio.h>
#include <stdlib.h>
// Pitfall 1: Forgetting to pass array size
void badFunction(int arr[]) {
// Can't determine size - need to pass it!
// printf("Size: %zu\n", sizeof(arr) / sizeof(arr[0])); // WRONG!
// sizeof(arr) gives pointer size, not array size
}
void goodFunction(int arr[], int size) {
printf(" Good: received array of size %d\n", size);
}
// Pitfall 2: Assuming array is copied
void modifyArray(int arr[], int size) {
for (int i = 0; i < size; i++) {
arr[i] *= 2; // Modifies original!
}
}
// Pitfall 3: Returning pointer to local array
int* badReturn() {
int local[5] = {1, 2, 3, 4, 5};
return local; // WRONG! local array goes out of scope
}
int* goodReturn() {
int *arr = malloc(5 * sizeof(int));
if (arr) {
for (int i = 0; i < 5; i++) arr[i] = i + 1;
}
return arr; // OK - heap allocation
}
// Pitfall 4: Incorrect multi-dimensional array parameter
// void bad2D(int arr[][]) { } // WRONG - need second dimension
void good2D(int arr[][5], int rows) { // OK
printf(" Good2D: received %d x 5 array\n", rows);
}
// Best Practice 1: Use const for read-only arrays
void printArrayConst(const int arr[], int size) {
printf(" Const array: ");
for (int i = 0; i < size; i++) {
printf("%d ", arr[i]);
// arr[i] = 0; // ERROR - can't modify
}
printf("\n");
}
// Best Practice 2: Use size_t for array sizes
void processArraySizeT(const int arr[], size_t size) {
printf(" Using size_t: array has %zu elements\n", size);
}
// Best Practice 3: Validate array parameters
int safeArrayOperation(int arr[], int size, int index, int value) {
if (arr == NULL) {
printf(" Error: NULL array pointer\n");
return -1;
}
if (index < 0 || index >= size) {
printf(" Error: Index %d out of bounds [0, %d]\n", index, size - 1);
return -1;
}
arr[index] = value;
return 0;
}
// Best Practice 4: Document array parameters
/**
* Calculate sum of array elements
* @param arr Array of integers (must not be NULL)
* @param size Number of elements (must be > 0)
* @return Sum of all elements
*/
int arraySum(const int arr[], int size) {
int sum = 0;
for (int i = 0; i < size; i++) {
sum += arr[i];
}
return sum;
}
int main() {
printf("=== Common Pitfalls and Best Practices ===\n\n");
int numbers[] = {10, 20, 30, 40, 50};
int size = sizeof(numbers) / sizeof(numbers[0]);
printf("Pitfall 1: Size information lost\n");
printf(" In main: sizeof(numbers) = %zu\n", sizeof(numbers));
printf(" In function: can't determine size\n");
goodFunction(numbers, size);
printf("\nPitfall 2: Modifications affect original\n");
printf(" Before: %d\n", numbers[0]);
modifyArray(numbers, size);
printf(" After: %d\n", numbers[0]);
printf("\nPitfall 3: Returning local array\n");
// int *bad = badReturn(); // Would return invalid pointer
int *good = goodReturn();
printf(" Good return: first element = %d\n", good[0]);
free(good);
printf("\nPitfall 4: 2D array parameters\n");
int matrix[3][5];
good2D(matrix, 3);
printf("\nBest Practices:\n");
printArrayConst(numbers, size);
processArraySizeT(numbers, size);
int result = safeArrayOperation(numbers, size, 2, 100);
printf(" Safe operation result: %d\n", result);
printf(" numbers[2] now: %d\n", numbers[2]);
result = safeArrayOperation(numbers, size, 10, 200);
printf(" Safe operation with bad index: %d\n", result);
printf("\nDocumentation example:\n");
printf(" Sum = %d\n", arraySum(numbers, size));
return 0;
}
Performance Considerations
#include <stdio.h>
#include <time.h>
// Passing large arrays by pointer (the only way)
void processLargeArray(int arr[], int size) {
// Do something trivial
int sum = 0;
for (int i = 0; i < size; i += 1000) {
sum += arr[i];
}
}
// Compare passing array vs passing individual elements (would be terrible)
// void processEachElement(int a1, int a2, int a3, ... ) - impractical
// Cache effects - processing order matters
void processRowMajor(int matrix[][1000], int rows, int cols) {
int sum = 0;
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
sum += matrix[i][j];
}
}
}
void processColumnMajor(int matrix[][1000], int rows, int cols) {
int sum = 0;
for (int j = 0; j < cols; j++) {
for (int i = 0; i < rows; i++) {
sum += matrix[i][j];
}
}
}
int main() {
printf("=== Performance Considerations ===\n\n");
const int LARGE_SIZE = 10000000;
int *largeArray = malloc(LARGE_SIZE * sizeof(int));
if (largeArray) {
// Initialize
for (int i = 0; i < LARGE_SIZE; i++) {
largeArray[i] = i;
}
clock_t start = clock();
processLargeArray(largeArray, LARGE_SIZE);
clock_t end = clock();
printf("Processing large array (10M elements): %.3f seconds\n",
(double)(end - start) / CLOCKS_PER_SEC);
printf("Note: No copying - passed by reference\n");
free(largeArray);
}
printf("\nKey performance points:\n");
printf(" 1. Arrays are always passed by reference - no copying overhead\n");
printf(" 2. Only the pointer (8 bytes) is passed, regardless of array size\n");
printf(" 3. Cache locality matters for multi-dimensional arrays\n");
printf(" 4. Row-major order (C style) is most efficient\n");
return 0;
}
Summary Table
| Declaration | Meaning | Can Determine Size? |
|---|---|---|
void func(int arr[]) | Pointer to int | No - need separate size |
void func(int *arr) | Pointer to int | No - need separate size |
void func(int arr[10]) | Still a pointer! | No - 10 is ignored |
void func(int arr[][5]) | Pointer to array of 5 ints | Knows second dimension |
void func(int *arr[]) | Array of pointers | No - need separate size |
Conclusion
Passing arrays to functions is a fundamental skill in C programming that leverages the language's pointer semantics for efficiency and flexibility. Key takeaways:
- Arrays are always passed by reference - modifications affect the original
- Size must be passed separately - functions don't know array length
- Different syntax options -
arr[]and*arrare equivalent in parameters - Multi-dimensional arrays require all but the first dimension specified
- Const qualifier protects read-only arrays from modification
- Pointer arithmetic offers alternative access methods
- Array slices can be passed by pointing to different start positions
By mastering array passing techniques, C programmers can write reusable, efficient functions that work with arrays of any size, implement complex algorithms, and build modular, maintainable code.