The address you get back from shmat() is a virtual address, as is any address which can be used directly as a pointer. Virtual addresses are indirect: they effectively point into address translation tables (page tables) which tell the CPU whether the corresponding memory is actually mapped, and where to find it in physical memory. On most Unix-style multi-tasking systems where processes are protected from each other, each process gets its own virtual address space.
Shared memory is a single set of physical pages which are mapped into multiple processes’ virtual address spaces. Since each process is liable to use its virtual address space differently, the same shared memory is liable to end up at different virtual addresses inside each process sharing it. Otherwise, a process with something already allocated at the required address wouldn’t be able to access a given piece of shared memory.
(There are systems where the virtual address space is the same across processes; see single address-space operating systems for details.)