What are Wild Pointers in C- C Programming For Beginners

Need Help or More Information?

Questions about this free C programming course, embedded C training or career guidance? Get in touch.

Wild Pointers in C

Why an uninitialised pointer breaks scanf, how to fix it, and how the same bug behaves on a microcontroller. Free C programming course for embedded systems.

free c programming coursefree c tutorialc programming for embedded systemsembedded c programmingwild pointer in c

What You Will Learn in This Lecture

  • What a wild (uninitialised) pointer is and why it is the most common pointer bug in embedded C programming
  • Why scanf("%d", ptr) is dangerous when ptr was never assigned
  • Three safe ways to give a pointer a valid target: an existing variable, heap memory, or NULL
  • How the compiler, -fsanitize=address and a debugger help you catch the problem early
  • What the same bug looks like on a microcontroller with memory-mapped peripherals

Prerequisites

You need the pointer basics from earlier in this free C tutorial: declaring a pointer, the address-of operator &, and dereferencing with *. Knowing how scanf receives addresses is also helpful.

What Is a Wild Pointer in C?

A wild pointer is a pointer variable that has been declared but never assigned a valid address. Declaring int *ptr; creates storage for an address, but C does not clear it. A local pointer holds whatever bytes were left in that stack slot by earlier code, so it may point into the stack, into the heap, into read-only memory or at nothing mapped at all. A global or static pointer is different: it starts as NULL because static storage is zero-initialised. That difference is why the same source line can appear to work in one program and crash in another.

Three states of a pointer variable

Wild ptr → ??? (random address)
Null ptr → NULL (points to nothing, safe to test)
Valid ptr → value (a real object)

Only the third state may be dereferenced. The second can be tested with if (ptr != NULL). The first cannot be tested at all, which is exactly what makes it dangerous.

The scanf Bug: Writing Through an Uninitialised Pointer

scanf does not read into variables; it **writes to addresses** you hand it. For %d it expects an int *. When that pointer is wild, scanf happily stores the converted number at an unknown location.

int *ptr;                 /* never given a target                */
scanf("%d", ptr);         /* scanf stores the number AT ptr      */
printf("%d\n", *ptr);     /* reads from the same unknown address */

The behaviour of this fragment is undefined. In practice you may see a segmentation fault, silent corruption of a neighbouring variable, or an apparently correct result that fails on another machine or compiler setting. All three are possible, and the third is the worst because testing does not reveal it.

Warning: Do not run the fragment above to see what happens. The result is not reproducible, and on a bare-metal target an unlucky address can be a peripheral register or the vector table.

Fixing the Bug: Three Ways to Give a Pointer a Target

ApproachCodeWhen to use it
Point at an existing objectint v; int *p = &v;Small, short-lived data that already has a name
Allocate memoryint *p = malloc(sizeof *p);Size or lifetime is not known at compile time (check for NULL, then free)
Initialise to NULLint *p = NULL;The target is not known yet; you will test before use

The program below uses the first two approaches and checks the return value of scanf, which is a habit worth keeping in every program.

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    int value = 5;
    int *ptr = &value;          /* valid target */

    printf("Enter a number: ");
    if (scanf("%d", ptr) != 1) {
        puts("bad input");
        return 1;
    }
    printf("value = %d, *ptr = %d\n", value, *ptr);

    int *heap = malloc(sizeof *heap);   /* second safe way: own storage */
    if (heap == NULL)
        return 1;
    if (scanf("%d", heap) == 1)
        printf("heap holds %d\n", *heap);
    free(heap);
    return 0;
}
gcc -std=c17 -Wall -Wextra -o wild_safe wild_safe.c
printf '16\n77\n' | ./wild_safe

Expected output (the input is piped in, so the prompt and the result share a line):

Enter a number: value = 16, *ptr = 16
heap holds 77

value and *ptr agree because ptr holds the address of value; writing through the pointer changes the variable itself. sizeof *heap is preferred over sizeof(int) because it stays correct if the pointer type is changed later.

Why value and *ptr print the same number

Stack ptr → value = 16
scanf receives the address held in ptr → writes 16 into value

The Same Bug on a Microcontroller

On a desktop, a wild pointer usually ends with a segmentation fault and a message, which is at least loud. On a bare-metal microcontroller there is often no memory protection. A wild pointer that happens to hold a peripheral address can toggle a pin, change a clock setting or start a DMA transfer. A wild pointer into flash silently ignores writes. A wild pointer into the stack corrupts return addresses. Symptoms appear far from the cause, which is why embedded teams treat uninitialised pointers as a serious defect rather than a style issue.

Detecting Wild Pointer Problems Early

  • Compile with -Wall -Wextra; modern GCC and Clang warn about many uses of uninitialised variables, especially with optimisation enabled.
  • Build test code with -fsanitize=address,undefined to turn silent corruption into an immediate report with a line number.
  • Run under valgrind for programs where sanitizers are not available.
  • In a debugger, watch the pointer value: addresses like 0xcccccccc or 0xdeadbeef are classic fill patterns, not real objects.
  • Initialise at the point of declaration. If you cannot, set the pointer to NULL.

Common Mistakes and Troubleshooting

MistakeWhy it is wrongFix
int *p; *p = 10;Stores through an unknown addressAssign p = &x; or allocate first
char *name; scanf("%s", name);Same bug with a string; also no length limitUse a char buf[32] and %31s, or fgets
Using a pointer after free(p)p is now dangling, a close cousin of wildSet p = NULL; right after free
Returning &local from a functionThe local object no longer existsReturn a static object, heap memory, or fill a caller-supplied buffer
Not checking malloc resultNULL dereference on allocation failureTest for NULL before the first use

Best Practices, Performance and Security

  • Declare a pointer at the moment you can give it a value; avoid declaring a block of pointers at the top of a function.
  • NULL is a cheap and reliable sentinel; the cost of a comparison is negligible next to the cost of the bug.
  • Security: an uninitialised pointer that is later written with attacker-influenced data is a classic route to memory corruption exploits. Treat every scanf or read target as untrusted memory.
  • Always check the return value of scanf; it tells you how many items were converted, and a failed conversion leaves the target unchanged.
  • In safety-critical coding standards such as MISRA C, using an object before it is initialised is explicitly prohibited.

Summary and Key Takeaways

  • A pointer that is declared but not assigned is wild, and dereferencing it is undefined behaviour.
  • scanf writes through the address it receives, so that address must be valid.
  • Safe sources of a valid address: &variable, malloc, or a documented fixed address on hardware.
  • Initialise to NULL when you cannot assign a real target yet.
  • Sanitizers and compiler warnings catch most of these bugs before they reach hardware.

Conclusion

Wild pointers cost more debugging time than almost any other C mistake because the program often seems fine until something unrelated changes. The cure is a discipline, not a trick: every pointer has a valid target or NULL from the line it is declared. With that habit in place, the next lecture in this free embedded C course can focus on a subtler point, the difference between an array name and a pointer variable.

Frequently Asked Questions

What is a wild pointer?

A wild pointer is a pointer that has not been initialised, so it holds an indeterminate address. Dereferencing it is undefined behaviour.

Why does scanf crash when I pass an uninitialised pointer?

scanf stores the converted value at the address you pass. An uninitialised pointer holds a random address, so the store may hit unmapped or protected memory.

Is a global pointer also wild?

No. Objects with static storage duration, including global pointers, are zero-initialised, so a global pointer starts as NULL unless you give it a value.

What is the difference between a wild pointer and a dangling pointer?

A wild pointer was never assigned. A dangling pointer was valid once but the object it pointed to has been freed or has gone out of scope.

How do I avoid wild pointers in embedded C programming?

Initialise every pointer at declaration, set pointers to NULL after free, enable compiler warnings, and use static analysis tools in your build.

Does -Wall always warn about uninitialised pointers?

Not always. Warnings depend on optimisation level and control flow, so combine -Wall -Wextra with sanitizers and code review.

Finish the Free Embedded C Course

Move on to the next pointer lecture and keep building your embedded C skills at no cost.

Need Help or More Information?

Questions about this free C programming course, embedded C training or career guidance? Get in touch.

2 Comments

Leave a Reply

Your email address will not be published. Required fields are marked *