Effect of Copy-On-Write on 2 processes sharing address space
The fork primitive makes a copy of the process. From within the processes, the parent and the child are almost identical; the few differences are the return value of the fork primitive and a few characteristics such as the process ID.

Copy-on-write is an implementation optimization. It isn't visible from inside the process. You'd need to look inside the kernel to see it, or use some reporting tools that expose this information. For example, you can observe it indirectly through memory usage statistics.

What you're printing out are the virtual addresses of the variables. They're the same: that's the whole point of fork — it creates a (near-)identical copy of the process.

Under the hood, when the child modifies the value of a, the kernel makes a copy of the page that contains it. Before that point, the variable a in the parent process and in the child process are stored in the same memory. After that point, they are stored in different memory: the parent and the child now each have their own page. But the two processes map their respective pages at the same address — the address of a variable doesn't change (it can't change, because that's how the code locates the variable).