CodeWithAbdessamad

Pointer Basics

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

  1. The asterisk (*) always precedes the variable name (not part of the name)
  2. Pointers must be initialized to avoid undefined behavior
  3. 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. The 0x0 output 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 = &num;  // 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 = &num;</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 NULL to 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.