C ProgrammingUnit 612 min read
Arrays in C – Definitions, Types, Operations, Pointer Relations & Common Algorithms
Unit 6 of C Programming provides a comprehensive note on arrays, covering one‑ and multi‑dimensional arrays, memory layout, pointer relationship, common manipulations (input, output, sum, average, sorting, matrix operations) and typical exam‑style programs.
Key points
- An array is a contiguous block of memory holding elements of the same data type, accessed by index.
- One‑dimensional and multi‑dimensional arrays differ only in how the index calculation is performed.
- The name of an array is a constant pointer to its first element, enabling pointer arithmetic.
- Common array algorithms (sum, average, second largest, sorting, matrix addition, transpose) are frequently asked in TU exams.
- Proper bounds checking, initialization and use of `sizeof` prevent common runtime errors.
1. What is an Array?
An array in C is a collection of objects of the same type stored in contiguous memory locations. The compiler allocates a fixed amount of memory at compile time (for static arrays) or at run time (for dynamic arrays using malloc).
int scores[5]; // 5 integers, indices 0 … 4
char name[20]; // 20 characters, indices 0 … 19
float matrix[3][3]; // 3×3 float matrix, total 9 elements
Benefits of using arrays
| Benefit | Explanation |
|---|---|
| Random access | Any element can be accessed directly using its index, O(1) time. |
| Compact storage | No extra pointers are needed; memory is contiguous, improving cache performance. |
| Ease of iteration | Loops can process all elements uniformly. |
| Facilitates algorithms | Sorting, searching, matrix arithmetic become straightforward. |
| Interoperability | Many library functions (e.g., printf, scanf, qsort) expect arrays. |
2. Memory Layout and Index Calculation
For a one‑dimensional array T a[N], the address of a[i] is:
For a two‑dimensional array T a[R][C] (row‑major order in C):
Thus, a 2‑D array is stored as a single linear block; the compiler performs the index arithmetic automatically.
3. Declaring, Initializing, and Accessing Arrays
3.1 Static Initialization
int primes[5] = {2, 3, 5, 7, 11};
char vowel[] = {'a','e','i','o','u'}; // size inferred as 5
float zeros[4] = {0.0}; // first element 0.0, rest also 0.0
If fewer initializers are supplied than the declared size, the remaining elements are zero‑initialized.
3.2 Dynamic Allocation
int *dyn = malloc(10 * sizeof(int)); // space for 10 integers
if (!dyn) { perror("malloc"); exit(EXIT_FAILURE); }
Remember to free(dyn) when done.
3.3 Input & Output
for (int i = 0; i < 5; ++i) {
printf("Enter element %d: ", i);
scanf("%d", &arr[i]);
}
printf("%d ", arr[i]); prints each element.
4. One‑Dimensional vs Two‑Dimensional Arrays
| Feature | One‑Dimensional Array | Two‑Dimensional Array |
|---|---|---|
| Syntax | type name[size]; |
type name[rows][cols]; |
| Indexing | Single index a[i] |
Double index a[i][j] |
| Memory | Linear block of size elements |
Linear block of rows*cols elements, accessed row‑wise |
| Typical Use | Lists, vectors, queues | Matrices, tables, image pixels |
| Example | int ages[500]; |
int matrix[3][3]; |
5. Relationship Between Arrays and Pointers
- The array name (e.g.,
arr) decays to a pointer to its first element (&arr[0]) in most expressions. - Pointer arithmetic on this decayed pointer yields the same addresses as array indexing.
int a[5] = {10,20,30,40,50};
int *p = a; // same as int *p = &a[0];
printf("%d %d\n", *(p+2), a[2]); // both print 30
5.1 Pointer and One‑Dimensional Array Example
void modify(int *ptr, int n) {
for (int i = 0; i < n; ++i)
*(ptr + i) = *(ptr + i) * 2; // double each element
}
int main(void) {
int data[4] = {1,2,3,4};
modify(data, 4); // data decays to pointer
// data now holds {2,4,6,8}
}
6. Call‑by‑Value vs Call‑by‑Reference
| Aspect | Call‑by‑Value | Call‑by‑Reference |
|---|---|---|
| Argument passing | Copies the actual value into the parameter. | Passes the address (pointer) of the argument. |
| Effect on original variable | No change to caller’s variable. | Caller’s variable can be modified. |
| Typical use with arrays | Arrays automatically decay to pointers → effectively call‑by‑reference. | Explicit pointer parameters for single variables. |
| Example | void f(int x){ x = 5; } – original unchanged. |
void g(int *p){ *p = 5; } – original becomes 5. |
Program demonstrating both concepts
#include <stdio.h>
void byValue(int x) { // copy of x
x = x + 10;
printf("Inside byValue: %d\n", x);
}
void byReference(int *p) { // address of original
*p = *p + 10;
printf("Inside byReference: %d\n", *p);
}
int main(void) {
int a = 5;
printf("Original a: %d\n", a);
byValue(a); // a remains 5
printf("After byValue: %d\n", a);
byReference(&a); // a becomes 15
printf("After byReference: %d\n", a);
return 0;
}
7. Common Array Algorithms
7.1 Sum and Average of N Numbers
#define N 10
int main(void) {
int arr[N];
int sum = 0;
for (int i = 0; i < N; ++i) {
scanf("%d", &arr[i]);
sum += arr[i];
}
double avg = (double)sum / N;
printf("Sum = %d, Average = %.2f\n", sum, avg);
return 0;
}
7.2 Second Largest Element
int secondLargest(int *a, int n) {
int largest = INT_MIN, second = INT_MIN;
for (int i = 0; i < n; ++i) {
if (a[i] > largest) {
second = largest;
largest = a[i];
} else if (a[i] > second && a[i] != largest) {
second = a[i];
}
}
return second;
}
7.3 Sorting an Array (Ascending) – Simple Bubble Sort
void bubbleSort(int *a, int n) {
for (int i = 0; i < n-1; ++i)
for (int j = 0; j < n-i-1; ++j)
if (a[j] > a[j+1]) {
int tmp = a[j];
a[j] = a[j+1];
a[j+1] = tmp;
}
}
7.4 Matrix Addition
#define ROW 3
#define COL 3
void addMatrices(int A[ROW][COL], int B[ROW][COL], int C[ROW][COL]) {
for (int i = 0; i < ROW; ++i)
for (int j = 0; j < COL; ++j)
C[i][j] = A[i][j] + B[i][j];
}
Full program (adds two 3×3 matrices and prints result)
#include <stdio.h>
#define ROW 3
#define COL 3
int main(void) {
int A[ROW][COL], B[ROW][COL], C[ROW][COL];
printf("Enter elements of first matrix (3x3):\n");
for (int i = 0; i < ROW; ++i)
for (int j = 0; j < COL; ++j)
scanf("%d", &A[i][j]);
printf("Enter elements of second matrix (3x3):\n");
for (int i = 0; i < ROW; ++i)
for (int j = 0; j < COL; ++j)
scanf("%d", &B[i][j]);
// addition
for (int i = 0; i < ROW; ++i)
for (int j = 0; j < COL; ++j)
C[i][j] = A[i][j] + B[i][j];
printf("Resultant matrix:\n");
for (int i = 0; i < ROW; ++i) {
for (int j = 0; j < COL; ++j)
printf("%4d", C[i][j]);
printf("\n");
}
return 0;
}
7.5 Transpose of a Matrix
void transpose(int src[ROW][COL], int dest[COL][ROW]) {
for (int i = 0; i < ROW; ++i)
for (int j = 0; j < COL; ++j)
dest[j][i] = src[i][j];
}
Worked trace (3×2 matrix)
src = [ 1 2 ]
[ 3 4 ]
[ 5 6 ]
After transpose (2×3):
dest = [ 1 3 5 ]
[ 2 4 6 ]
8. Practical Example: Age Statistics of 500 Persons
#include <stdio.h>
#define PERSONS 500
int main(void) {
int age[PERSONS];
long sum = 0;
int count_25_30 = 0;
for (int i = 0; i < PERSONS; ++i) {
scanf("%d", &age[i]);
sum += age[i];
if (age[i] >= 25 && age[i] <= 30)
++count_25_30;
}
double avg = (double)sum / PERSONS;
printf("Average age = %.2f\n", avg);
printf("Number of persons aged 25‑30 = %d\n", count_25_30);
return 0;
}
9. Advantages, Disadvantages, and Typical Applications
| Aspect | Advantages | Disadvantages | Typical Applications |
|---|---|---|---|
| Static arrays | Compile‑time size, no runtime overhead, fast access. | Fixed size; cannot grow/shrink. | Fixed‑size buffers, lookup tables, embedded systems. |
Dynamic arrays (malloc) |
Size decided at run time, can be large. | Need explicit free; fragmentation risk. |
Large data sets, user‑defined size structures, runtime matrices. |
| Multi‑dimensional arrays | Natural representation of matrices, images, grids. | Index calculation can be error‑prone; large stack usage if declared locally. | Scientific computing, graphics, game boards. |
| Array‑pointer equivalence | Enables generic functions (void *, qsort). |
Misunderstanding can lead to off‑by‑one bugs. | Library APIs, generic algorithms. |
10. Common Pitfalls and How to Avoid Them
- Off‑by‑one errors – Remember that valid indices are
0tosize‑1. - Uninitialized elements – Static arrays without explicit initializer contain indeterminate values; always initialize.
- Array‑pointer decay confusion –
sizeof(arr)gives total size, whilesizeof(ptr)gives pointer size. Usesizeof(arr)/sizeof(arr[0])for element count. - Boundary checks – Never read/write beyond allocated bounds; use loops that respect the declared size.
- Mixing row‑major vs column‑major – C uses row‑major; transposition code must swap indices accordingly.
11. Summary of Key Functions Used
| Function | Purpose | Prototype |
|---|---|---|
scanf |
Input from console | int scanf(const char *fmt, …); |
printf |
Output to console | int printf(const char *fmt, …); |
malloc |
Dynamic memory allocation | void *malloc(size_t size); |
free |
Release dynamic memory | void free(void *ptr); |
qsort |
Generic sorting (optional) | void qsort(void *base, size_t nitems, size_t size, int (*compar)(const void *, const void *)); |
12. Worked Example: Full Program Combining Several Concepts
The following program reads 10 integers, prints the sum, average, second largest, and then sorts the array in ascending order.
#include <stdio.h>
#include <limits.h>
#define N 10
int secondLargest(int *a, int n) {
int largest = INT_MIN, second = INT_MIN;
for (int i = 0; i < n; ++i) {
if (a[i] > largest) {
second = largest;
largest = a[i];
} else if (a[i] > second && a[i] != largest) {
second = a[i];
}
}
return second;
}
void bubbleSort(int *a, int n) {
for (int i = 0; i < n-1; ++i)
for (int j = 0; j < n-i-1; ++j)
if (a[j] > a[j+1]) {
int tmp = a[j];
a[j] = a[j+1];
a[j+1] = tmp;
}
}
int main(void) {
int arr[N];
int sum = 0;
printf("Enter %d integers:\n", N);
for (int i = 0; i < N; ++i) {
scanf("%d", &arr[i]);
sum += arr[i];
}
double avg = (double)sum / N;
int sec = secondLargest(arr, N);
bubbleSort(arr, N);
printf("\nSum = %d\n", sum);
printf("Average = %.2f\n", avg);
printf("Second largest = %d\n", sec);
printf("Sorted array: ");
for (int i = 0; i < N; ++i)
printf("%d ", arr[i]);
printf("\n");
return 0;
}
Trace of execution (sample input)
Input: 5 12 7 3 9 20 15 8 11 4
Sum = 94
Average = 9.40
Second largest = 15
Sorted array: 3 4 5 7 8 9 11 12 15 20
13. Frequently Asked Questions (FAQ)
Q: Can I pass a whole 2‑D array to a function?
A: Yes, but you must specify the second dimension (or use a pointer to an array). Example:void func(int a[][COL], int rows);Q: What is the difference between
int a[10];andint *a = malloc(10*sizeof(int));?
A: The first is a static array allocated on the stack with compile‑time size; the second is a dynamic array on the heap, size decided at run time, and must be freed.Q: Why does
sizeof(arr)give a different result inside a function?
A: Inside a function,arrdecays to a pointer, sosizeof(arr)yields the size of the pointer (typically 4 or 8 bytes), not the total array size.
14. Best Practices
- Always use constants for sizes (
#define MAX 500orconst int MAX = 500;) to avoid magic numbers. - Prefer
size_tfor loop counters when dealing withsizeof. - Initialize arrays at declaration when possible.
- Encapsulate repeated logic (e.g., input, printing) into functions to keep
mainclean. - Use
constqualifier for arrays that should not be modified, especially when passing to functions.
Exam tip
- Read the question carefully: Most TU exam items ask for a specific operation (e.g., “find transpose”, “second largest”). Write only the required code; extra functions may cost marks.
- Show array declaration and size explicitly; examiners often look for correct syntax (
int a[5][5];). - Include a brief comment indicating what each loop does; it demonstrates understanding and can earn partial credit even if a minor syntax error occurs.
- Remember pointer decay: When a function expects a pointer, you can pass the array name directly. If the question asks to “discuss relationship”, write the formula
array[i] == *(array + i). - Edge cases: For algorithms like second largest, handle duplicate maximum values; a simple
INT_MINinitialization avoids undefined behavior. - Time management: Allocate ~2 minutes per short program (input‑output, sum/average) and ~5 minutes for multi‑step tasks (matrix addition, transpose). Write clean, indented code to avoid syntax mistakes that cost marks.
Based on the TU BSc CSIT syllabus for C Programming (CSC115), unit 6.
Discussion
Loading…