An array is a fixed-size, sequential collection of elements of the same data type. Elements are stored in contiguous memory locations.
int numbers[5]; // Declares an array of 5 integers numbers[0] = 10; // Access is 0-indexed
// Declares a 2D array with 3 rows and 4 columns int matrix[3][4]; matrix[1][2] = 5; // Access row 1, column 2
In memory, 2D arrays are stored in row-major order (all of row 0, then all of row 1, etc.).
When you pass an array to a function, you are actually passing a pointer to its first element. The function can modify the original array.
// Both function prototypes are identical:
void printArray(int arr[], int size);
void printArray(int *arr, int size);
void modify(int arr[]) {
arr[0] = 100; // This changes the ORIGINAL array
}
int main() {
int data[3] = {1, 2, 3};
modify(data);
printf("%d", data[0]); // Prints 100
return 0;
}
In C, a string is simply a one-dimensional array of char that is terminated by a special null character ('\0').
char name[] = "Hello"; // 6 bytes: 'H','e','l','l','o','\0' char str[10]; // Can hold a string of up to 9 chars + null
A pointer is a variable whose value is the memory address of another variable.
Two key operators:
& (Address-of operator): Gets the memory address of a variable.* (Dereference/Indirection operator): Gets the value *at* a given memory address.
int x = 10;
int *ptr; // 'ptr' is a pointer to an integer
ptr = &x; // 'ptr' now holds the address of 'x'
printf("%d\n", *ptr); // Prints 10 (the value at the address)
*ptr = 20; // Changes the value of 'x' to 20
printf("%d\n", x); // Prints 20
The data type of the pointer must match the data type of the variable it points to.
int *i_ptr; // Pointer to an int char *c_ptr; // Pointer to a char float *f_ptr; // Pointer to a float
To modify a variable from main() inside another function, you must pass a pointer to it. This is called "pass by reference."
// 'x_ptr' holds the address of 'num'
void increment(int *x_ptr) {
(*x_ptr) = (*x_ptr) + 1; // Modifies the original 'num'
}
int main() {
int num = 10;
increment(&num); // Pass the address of 'num'
printf("%d\n", num); // Prints 11
return 0;
}
In C, pointers and arrays are very closely related. The name of an array "decays" to a pointer to its first element.
arris equivalent to&arr[0]
arr[i]is equivalent to*(arr + i)
int arr[5] = {10, 20, 30, 40, 50};
int *ptr = arr; // Same as int *ptr = &arr[0];
printf("%d\n", arr[2]); // Prints 30
printf("%d\n", *(arr + 2)); // Prints 30
printf("%d\n", ptr[2]); // Prints 30
printf("%d\n", *(ptr + 2)); // Prints 30
When you add an integer n to a pointer ptr, the address is not incremented by n. It is incremented by n * sizeof(*ptr).
This is why ptr + 1 automatically points to the *next element* in an array, regardless of whether it's an int (4 bytes) or char (1 byte).
A pointer to a char is often used to work with strings.
char *str = "Hello World"; // Points to a string literal
// This string is read-only!
// A common C function using char pointers
int str_length(char *s) {
int len = 0;
while (*s != '\0') {
len++;
s++; // Move pointer to next character
}
return len;
}
This is an array where each element is a pointer. This is often used to store a list of strings.
// 'names' is an array of 3 pointers to char
char *names[3] = {
"Alice",
"Bob",
"Charlie"
};
printf("%s\n", names[1]); // Prints "Bob"
A "double pointer" stores the address of *another pointer*.
int x = 10;
int *p = &x; // 'p' points to 'x'
int **pp = &p; // 'pp' points to 'p'
printf("%d\n", **pp); // Prints 10 (dereference twice)
This is used for functions that need to modify a pointer (e.g., in dynamic memory allocation) and for argv in main().
The name of a 2D array matrix decays to a pointer to its first *row*. This is a "pointer to an array," not a "pointer to a pointer."
int matrix[2][3] = {{1,2,3}, {4,5,6}};
// 'p' is a pointer to an array of 3 integers
int (*p)[3] = matrix;
printf("%d\n", *(*(p + 1) + 2)); // Prints 6 (matrix[1][2])
int *p[3] (array of 3 pointers to int) is very different from int (*p)[3] (pointer to one array of 3 ints). This is a common exam question.
C programs can receive arguments from the command line when executed (e.g., ./myprog file.txt). This is handled by main()'s parameters.
// argc: Argument Count (number of strings)
// argv: Argument Vector (array of strings)
int main(int argc, char *argv[]) {
printf("You ran the program with %d arguments.\n", argc);
// argv[0] is always the program's own name
printf("Program name: %s\n", argv[0]);
if (argc > 1) {
printf("First argument: %s\n", argv[1]);
}
return 0;
}
Just as pointers can store addresses of variables, they can also store the address of a function. This allows you to treat functions as arguments to other functions.
int add(int a, int b) { return a + b; }
int subtract(int a, int b) { return a - b; }
// 'funcPtr' is a pointer to a function that
// takes two ints and returns an int
int (*funcPtr)(int, int);
// Assign the pointer
funcPtr = &add; // or just funcPtr = add;
// Call the function via the pointer
int result = funcPtr(10, 5); // result is 15
// Re-assign the pointer
funcPtr = &subtract;
result = funcPtr(10, 5); // result is 5
// --- Passing functions to other functions ---
int doOperation(int x, int y, int (*op)(int, int)) {
return op(x, y);
}
int main() {
int sum = doOperation(20, 10, &add); // sum is 30
int diff = doOperation(20, 10, &subtract); // diff is 10
return 0;
}