1. What is a Pointer?
A pointer is a special type of variable that does not store a normal value (like 10, 'A', or 3.14). Instead, a pointer stores a memory address.
Analogy: A House and its Address
·
A normal variable (e.g., int num = 10;) is like
a house.
The house itself contains your "stuff" (the value 10).
· A pointer is like a piece of paper with the house's address written on it (e.g., "123 Main Street"). It doesn't contain the stuff, but it *tells you where to find* the stuff.
2. Why Use Pointers?
Pointers are arguably the most powerful (and most complex) feature in C. They are essential for:
· Dynamic Memory Allocation: Creating variables while the program is running (e.g., creating an array only if the user needs it). You'll see this in Unit 4.
·
Passing Arguments by Reference: Allowing
a function to modify its original input arguments (e.g., a swap function).
This is a *major* concept.
· Efficient Array Manipulation: Pointers and arrays are very closely related in C.
· Creating Complex Data Structures: Building things like Linked Lists, Trees, and Graphs (which use "self-referential structures").
3. Pointer Syntax: The Two Key Operators
To work with pointers, you must understand two special operators:
A. The `&` (Address-of) Operator
· This operator gets the memory address of a variable.
·
You've already used this in scanf("%d", &num);. You
weren't passing the variable num, you were
passing the address of
num so scanf knew
where to store the input.
int num = 10;
// &num means "the address of num"
printf("Value of num: %d\n", num);
printf("Address of num: %p\n", &num); // %p is the format specifier for printing addresses
B. The `*` (Dereference) Operator
· This operator is used in two different ways:
1. In a declaration: It declares a pointer variable.
2. In executable code: It "goes to" the address stored in the pointer and gets the value at that address. This is called "dereferencing".
4. Declaring and Using Pointers (Basic Example)
Let's put the & and * operators together.
/* * Example 1: Basic Pointer Demonstration * Shows how to declare, initialize, and dereference a pointer.*/
#include <stdio.h>
int main() {
// 1. Create a normal integer variable
int num = 25;
// 2. Declare a pointer variable
// 'ptr' is a variable that can hold the address of an integer
int *ptr;
// 3. Initialize the pointer
// Store the address of 'num' into 'ptr'
ptr = #
// --- Printing the values ---
printf("--- Printing 'num' (the variable) ---\n");
printf("Value of num: %d\n", num);
printf("Address of num: %p\n", &num);
printf("\n--- Printing 'ptr' (the pointer) ---\n");
printf("Value of ptr (it stores an address): %p\n", ptr);
printf("Address of the pointer itself: %p\n", &ptr);
printf("\n--- Using the Dereference Operator * ---\n");
printf("Value at the address ptr is pointing to: %d\n", *ptr); // This means "get the value at ptr"
// You can also change the original variable's value VIA the pointer
printf("\n--- Changing 'num' via 'ptr' ---\n");
*ptr = 50; // "Go to the address stored in ptr, and set the value there to 50"
printf("The new value of num is: %d\n", num); // num is now 50!
return 0;
}5. NULL Pointers
Sometimes you need a pointer that points to "nothing."
For this, we use NULL.
A NULL
pointer is a special value that represents an invalid
address. It's a good practice to initialize pointers to NULL if
you don't have a valid address for them yet. This prevents your program from
accidentally using a "wild" pointer that points to a random (and
dangerous) part of memory.
// Initialize ptr to NULL. It points to nothing.
int *ptr = NULL;
// You can check if a pointer is safe to use
if (ptr != NULL) {
// It's safe to dereference
printf("Value: %d\n", *ptr);
} else {
printf("The pointer is NULL and cannot be used.\n");
}6. Pointers and Arrays
This is a very important relationship in C.
The name of an array, by itself, acts as a constant pointer to its first element.
·
If you have int arr[10];
·
The expression arr is
equivalent to &arr[0]. Both give
you the memory address of the very first element in the array.
This means you can access array elements using pointer arithmetic:
·
arr[i] is
the standard way (array notation).
·
*(arr + i) is
the pointer notation way. It means:
1.
Start at the base address arr.
2.
Add i "units"
of memory to it (where a unit is sizeof(int)).
3. Go to that new address and get the value.
/* * Example 2: Pointers and Arrays * Shows how to access array elements using * both array notation and pointer notation.*/
#include <stdio.h>
int main() {
int nums[5] = {10, 20, 30, 40, 50};
int i;
printf("--- Accessing with Array Notation arr[i] ---\n");
for (i = 0; i < 5; i++) {
printf("nums[%d] = %d\n", i, nums[i]);
}
printf("\n--- Accessing with Pointer Notation *(arr + i) ---\n");
for (i = 0; i < 5; i++) {
printf("*(nums + %d) = %d\n", i, *(nums + i));
} printf("\n--- Showing Addresses ---\n");
printf("Address of first element (&nums[0]): %p\n", &nums[0]);
printf("Value of the array name (nums): %p\n", nums);
// Note: The two addresses above will be identical!
return 0;
}Pointers vs. Arrays (Advanced)
While they are similar, there is one key difference:
·
An array
name (e.g., nums) is
a constant pointer.
Its value (the address of the start of the array) is fixed and cannot be changed. You
cannot do nums++;.
·
A pointer
variable (e.g., int *ptr = nums;) is
a variable.
Its value can be
changed. You can do ptr++;, which
would make it point to the next element (nums[1]).