A pointer is an abstraction provided by a high-level language; in theory it could be any width at all. It's totally at the whim of the compiler.
In practice, it's typically related to the width of the memory addresses of the underlying hardware, as that's usually the most efficient thing for the compiler to implement. There are exceptions though; for example, C++'s pointer-to-member-function does not have a direct mapping to hardware addresses, as it needs to represent two entities (the function and some notion of the type).
However, even leaving that aside, there are still complexities. For example:
- On most modern hardware, your program will work with virtual memory addresses, rather than physical addresses (which may not be the same width). Unless you're writing kernel-space code.
- On some architectures (e.g. x86), the underlying hardware exhibits a segmented address space. This is really complicated, but is mostly abstracted away by the OS and the virtual-memory system. If you're writing kernel-space code or code for really old x86s, you'll have to deal with it, though.
- On current x86-64, (virtual) memory addresses are actually only 48-bits wide.
- x86-64 supports both 32-bit and 64-bit executables.
- You may be running inside a virtual machine, which again can do whatever if it wants (relative to the underlying physical machine).
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…