Another difference is when you are converting between integers of different sizes.
For example, if you are extracting an integer from a byte stream (say 16 bits for simplicity), with unsigned values, you could do:
i = ((int) b[j]) << 8 | b[j+1]
(should probably cast the 2nd byte, but I'm guessing the compiler will do the right thing)
With signed values you would have to worry about sign extension and do:
i = (((int) b[i]) & 0xFF) << 8 | ((int) b[i+1]) & 0xFF