1> Variable assignment is done to the amount of memory of the type of the variable (e.g., short is 2 bytes, int is 4 bytes, in 32 bit hardware, typically). Sign of the variable is not important in the assignment. What matters here is how you are going to access it.
main()
{ unsigned short int a=-4;
printf("%d",a);
}
When you assign to a 'short' (signed/unsigned) you assign the value to a '2 bytes' memory. Now if you are going to use '%d' in printf, printf will consider it 'integer' (4 bytes in your hardware) and the two MSBs will be 0 and hence you got [0|0](two MSBs) [-4] (two LSBs). Due to the new MSBs (introduced by %d in printf, migration) your sign bit is hidden in the LSBs and hence printf considers it unsigned (due to the MSBs being 0) and you see the positive value.
{ 00000000 00000000}{11111111 11111100}=65532
2> Passing %d to printf tells printf to treat the argument as a signed integer, regardless of what you actually pass.
main()
{ unsigned int a=-4;
printf("%d",a);
}
To get a negative value in this you need to use '%hd' in first case
To get a positive value in this you need to use '%u' in Second case