In order to see the exact steps the compiler has taken to represent your code, I examined the dissassembly.
Line 00324C2E copies the value of your global variable "val" into the CPU's eax register.
Line 00324C33 copies the value from eax into the "foo" function's local stack space.
Line 00324C39 copies the value of your global variable "val" into the CPU's ecx register.
Line 00324C3F adds one to the value in the ecx register.
Line 00324C42 copies the incremented value from the ecx register back to your global variable "var".
Line 00324C48 copies the unaffected copy of the value, which was stored in the "foo" function's local stack space (see line 00324C33 above), into the CPU's eax register. It's copied to the eax register because it is the value that is returned to the calling function ("main" in this case).
Therefore, 0 is returned from foo(), but the global variable "val" contains 1 after foo() has returned.
int foo()
{
00324C10 push ebp
00324C11 mov ebp,esp
00324C13 sub esp,0C4h
00324C19 push ebx
00324C1A push esi
00324C1B push edi
00324C1C lea edi,[ebp-0C4h]
00324C22 mov ecx,31h
00324C27 mov eax,0CCCCCCCCh
00324C2C rep stos dword ptr es:[edi]
return val++;
00324C2E mov eax,dword ptr ds:[0032F320h]
00324C33 mov dword ptr [ebp-0C4h],eax
00324C39 mov ecx,dword ptr ds:[32F320h]
00324C3F add ecx,1
00324C42 mov dword ptr ds:[32F320h],ecx
00324C48 mov eax,dword ptr [ebp-0C4h]
}