int
is 32 bits long. IntPtr
is as long as a pointer for your architecture. Therefore, a pointer can be stored into an int
only on 32 bit systems, while it can always be stored in an IntPtr
.
Notice that your "int as a return value" example does not use an int
to hold a pointer, but just to hold a numeric value. This does not mean that an int
is automatically the correct size though: the author of that P/Invoke signature should have gone to the documentation for GetForegroundWindow
and see that it returns a HWND
.
Then, from windef.h
in the Platform SDK (or this MSDN page) we can see that a HWND
is a HANDLE
which is a PVOID
which is... a pointer!
Therefore, as far as I can tell, that signature is wrong, as the size of the return value of GetForegroundWindow
depends on the architecture. Thus, it should also be an IntPtr
.
Update:
While it can be inferred from the above, I think it's worthwhile to explicitly point out that:
- Erroneously using
int
instead of IntPtr
in 32-bit applications will never cause a problem, even if they run on 64-bit Windows; since most applications are 32-bit at this point in time, this will let you get away such mistakes very often.
- Erroneously using
int
instead of IntPtr
in 64-bit applications is not guaranteed to cause problems, since it is quite possible that in practice the values being encountered will fit in the 32 bits of the int
. This further lessens the probability that a mistake will manifest as an application error.
Therefore, for an error to actually manifest there are three conditions that have to be satisfied at the same time:
- An
int
is used where an IntPtr
should be.
- The executable image is 64-bit.
- A value returned by some PInvoke call and stored as an
int
is actually larger than 32 bits.