Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Scan for outdated or missing drivers - takes under a minute3Clear out junk files and repair common Windows errorsiTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more
C and C++ pointers often become address-like values in machine code, but they are not unrestricted integers. The language treats them as values that designate objects or functions under rules about type, lifetime, alignment, and bounds. Operating systems and hardware add another layer: a process uses virtual addresses, while CPUs and devices may use different physical or bus addresses. To access device registers safely, software needs platform-specific mapping and I/O operations—not just a pointer cast or volatile.
What a pointer means in C and C++
A pointer is a typed value used to refer to an object or function. In real programs, implementations commonly represent pointers with address-like bits and translate pointer operations into machine instructions. That practical resemblance does not make a pointer an integer with permission to access any location whose numeric address seems right.
The language model is about objects and valid operations. A pointer can designate an object or function, designate the position one past an array object, be null, or be invalid. The C++ reference on pointers summarizes these categories; C’s object model likewise constrains storage and typed access. A 2018 C committee discussion paper, WG14 N2311, explores pointer provenance—the idea that a pointer’s validity may depend on how it was derived, not only on its numeric address. It is useful context, not normative final-standard wording.
Recommended Free Tools
What taking an address and dereferencing do
Taking an address
In int x = 7; int *p = &x; int y = *p;, &x produces a pointer designating the object x. The declaration int *p says that p is a pointer to int; it does not grant access to every address that could be interpreted as an integer.
#1 Best Overall
Dereferencing
*p is an expression that designates the pointed-to object. In this example, evaluating it to initialize y obtains the value stored in x. As the GNU C Language Manual’s Pointers section puts it, “The unary operator ‘*’ gets the data that a pointer points to—this is called dereferencing the pointer.” That description assumes the pointer is valid for the operation. It does not mean every dereference must cause a physical RAM read: a compiler may optimize or transform operations while preserving the behavior required by the language.
Validity, lifetime, alignment, and bounds
A null pointer, a dangling pointer to an object whose lifetime has ended, or a pointer that is misaligned or otherwise invalid cannot safely be dereferenced. The relevant rules depend on the operation and type. Pointer arithmetic is constrained to the relevant array object and its one-past position; the one-past pointer may be formed for permitted comparisons and arithmetic, but it does not designate an element that can be accessed. Numeric address coincidence alone does not establish that a pointer validly designates an object.
For C++, see the reference on pointer arithmetic and pointer values; for C, see the references on pointers and objects and effective type. These are technical summaries, not substitutes for the applicable language standard.
Why a process pointer is not necessarily a hardware address
On systems with virtual memory, a process normally works with virtual addresses. The CPU’s translation machinery maps those addresses to CPU physical memory locations. Devices may use a third address domain, such as bus or DMA addresses. An IOMMU or platform-specific bus mapping can make a device-visible address differ from both the CPU virtual address and the CPU physical address.
Linux’s 5.10 address-mapping documentation explicitly distinguishes CPU virtual, CPU physical, and bus addresses, and warns against assuming they can be converted with a simple numeric shortcut. The document includes older conversion interfaces that it labels superseded; use it for the conceptual distinction, not as current driver instructions. DMA setup must use the appropriate operating-system and platform interfaces for the target kernel and device.
How device registers are accessed
Memory-mapped I/O
With memory-mapped I/O (MMIO), a device exposes a register window that the CPU can access through load/store-like operations. The address range must first be discovered and mapped through the operating system’s interface. It is not enough to take a number from a device manual and cast it to an ordinary C or C++ pointer.
For Linux kernel drivers, the relevant family includes ioremap and typed accessors such as readX/writeX or ioreadX/iowriteX. Exact APIs and guarantees depend on kernel version and architecture. The Linux kernel’s device I/O documentation explains that a device physical address should be mapped to a CPU virtual address before access. These kernel facilities are not portable hosted C or C++ interfaces; user-space applications should use the supported OS or device-driver API for their platform.
Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchWindows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallOrdering and completion
Device interactions can depend on the order of reads and writes. The compiler, CPU, caches, and interconnect may transform, combine, cache, or defer operations in ways that are valid for ordinary memory but unsuitable for a device protocol. Correct ordering requires the right mapping attributes, accessor, and any required barrier for the architecture and device. A memory barrier is not a universal substitute for a proper mapping and accessor, and a barrier intended only for synchronization among CPUs may not provide the needed device-ordering guarantee.
Best Value
The Linux kernel’s version 6.4 “Accessing Devices” documentation states: “Inside of the Linux kernel, I/O should be done through the appropriate accessor routines – such as inb() or writel() – which know how to make such accesses appropriately sequential.” The rule is about kernel driver practice; the specific guarantee depends on the accessor and platform.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.What volatile does—and does not do
In C and C++, volatile affects how the compiler treats certain accesses to volatile objects. It is not a general-purpose hardware synchronization feature. By itself, it does not establish CPU ordering, cache coherency, bus completion, atomicity, or a portable MMIO interface.
That distinction matters because “the compiler emits an access” and “the device observes that access in the required order” are different claims. Linux kernel guidance directs driver code to use the appropriate I/O accessor routines; direct access through ordinary pointers does not work across all architectures. For a device, follow its operating system’s documented interfaces and the device’s ordering requirements rather than relying on volatile alone.
Quick Recap
Keep the two layers separate
| Question | C/C++ language layer | Platform and hardware layer |
|---|---|---|
| What does the pointer designate? | An object or function, subject to language rules for type, lifetime, alignment, and bounds. | An implementation may represent it as an address-like value and use CPU instructions to access storage. |
| What does an address identify? | A pointer value’s validity is governed by the language; numeric equality alone does not prove a valid object access. | Virtual, CPU physical, and device bus/DMA addresses may be distinct and require translation or mapping. |
| How is a device register accessed? | Pointer syntax and volatile do not define a portable MMIO interface. |
Use the OS’s mapping and I/O-accessor facilities, with platform-appropriate ordering. |
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

