Pointer Basics π
Pointers are one of C’s most powerful yet often misunderstood features. Think of them as direct memory addresses that let you interact with your program’s memory at a low level. This section covers the absolute fundamentals: how to declare pointers and how to work with addresses and dereferencing. Let’s build your foundation step by step.
Pointer Declaration
A pointer is a variable that stores the memory address of another variable. In C, you declare pointers by specifying the type of data they point to, followed by an asterisk (*), and then the variable name. The asterisk is criticalβit tells the compiler this is a pointer, not a regular variable.
Here’s the standard syntax:
<code class="language-c">type *pointer<em>variable</em>name;</code>
Key Rules for Declaration
- The asterisk (
*) always precedes the variable name (not part of the name) - Pointers must be initialized to avoid undefined behavior
- Pointer types must match what they point to
Example 1: Declaring an integer pointer
<code class="language-c">int num = 42; <p>int *p; // p is a pointer to an integer</code>
Example 2: Declaring a float pointer
<code class="language-c">float f = 3.14; <p>float *fp; // fp is a pointer to a float</code>
Example 3: Declaring a character pointer (common for strings)
<code class="language-c">char c = 'A'; <p>char *ch; // ch points to a single character</code>
Why Initialization Matters
Uninitialized pointers contain garbage values (random memory addresses) and cause undefined behavior. Always initialize pointers when you declare them:
<code class="language-c">int *ptr = NULL; // Safe initialization</code>
Let’s see this in action with a runnable example:
<code class="language-c">#include <stdio.h>
<p>int main() {</p>
<p> int num = 42;</p>
<p> int *p; // Pointer declaration</p>
<p> printf("Value of num: %d\n", num);</p>
<p> printf("Address of num: %p\n", (void*)&num);</p>
<p> printf("Uninitialized pointer p: %p\n", (void*)p);</p>
<p> return 0;</p>
<p>}</code>
Output:
<code>Value of num: 42 <p>Address of num: 0x7ffcd0a0</p> <p>Uninitialized pointer p: 0x0</code>
π‘ Pro Tip: In production code, always initialize pointers to
NULL(or a valid address) to prevent memory corruption. The0x0output above shows uninitialized pointers contain null addresses.
Address and Dereferencing
Now that we’ve declared pointers, let’s explore how to interact with memory addresses: first by getting an address, then by accessing the value at that address.
Getting the Address
The & operator returns the memory address of a variable:
<code class="language-c">int num = 10; <p>int *p = # // p now holds the address of num</code>
This is how we “find” where a variable lives in memory.
Dereferencing a Pointer
The * operator accesses the value stored at a memory address:
<code class="language-c">int num = 10; <p>int *p = #</p> <p>int value = *p; // value now equals 10</code>
This is called dereferencingβit “removes” the address and gives you the actual data.
Key Difference Summary
| Concept | Operator | Example | Purpose |
|---|---|---|---|
| Address of | & |
&num |
Gets memory address of a variable |
| Dereference | |
p |
Gets value at address stored in pointer |
Why This Matters
The operator has higher precedence than =. So p means “the value at address p“, not “pointer p multiplied by something”.
Let’s run a practical example:
<code class="language-c">#include <stdio.h>
<p>int main() {</p>
<p> int a = 10;</p>
<p> int *b = &a; // b points to a</p>
<p> int c = *b; // c gets value of a</p>
<p> printf("a = %d\n", a);</p>
<p> printf("b = %p (address of a)\n", (void*)b);</p>
<p> printf("c = %d (value of a)\n", c);</p>
<p> return 0;</p>
<p>}</code>
Output:
<code>a = 10 <p>b = 0x7ffcd0a0 (address of a)</p> <p>c = 10 (value of a)</code>
π Real-World Insight: This is how C handles pass-by-reference in functions. When you pass a pointer to a function, it directly modifies the original variable’s memory location.
Summary
- Pointer Declaration: Creates a variable that stores memory addresses (e.g.,
int *p) - Address Operation:
&gives the memory address of a variable - Dereference:
*accesses the value at a memory address - Critical Practice: Always initialize pointers to
NULLto prevent undefined behavior
These two concepts form the bedrock of all pointer operations. Master them, and you’ll gain control over your program’s memory with confidence. Next up: pointer arithmetic and dynamic memory allocation.