It's undefined behaviour because you're modifying a constant.
It's up to the compiler of course, but one way to implement consts is as a typed #define and wherever it sees "i" referenced it just replaces it with a typecheck and the value 10 (and it could also exist in memory in case anyone wants to take its address). And you're not going to fool a compiler with *(&i) - it knows these are inverse operations of each other so this is directly equivalent to i, which is 10 (because i is a const).
Looking at the generated assembly answers all. This is from Visual Studio 2005:
Code:
printf("%d %d\n",*(&i),*j);
00411762 mov esi,esp
00411764 mov eax,dword ptr [j]
00411767 mov ecx,dword ptr [eax]
00411769 push ecx
0041176A push 0Ah
0041176C push offset string "%d %d\n" (41CB8Ch)
00411771 call dword ptr [__imp__printf (4204A4h)]
and you can see at 0041176A that the literal value 10 is pushed onto the stack, NOT what is in memory at &i.