Assigning unsigned to signed types and vice versa
Let's explore the interactions between signed and unsigned variables in C with complete examples, including the binary representations in the outputs. These examples will illustrate the effects of sign and zero extension, especially in corner cases.
1. Unsigned to Signed Assignment
Example:
#include <stdio.h>
int main() {
unsigned int u = 4294967295; // Maximum unsigned int value
int s = u; // Assigning unsigned to signed
printf("Unsigned: %u, Binary: %x\n", u, u);
printf("Signed: %d, Binary: %x\n", s, s);
return 0;
}
Expected Output:
Unsigned: 4294967295, Binary: ffffffff
Signed: -1, Binary: ffffffff
Explanation: The maximum unsigned int, represented in binary as all 1s, becomes -1 in a signed int due to two's complement representation.
2. Signed to Unsigned Assignment
Example:
#include <stdio.h>
int main() {
int s = -1; // Negative signed int
unsigned int u = s; // Assigning signed to unsigned
printf("Signed: %d, Binary: %x\n", s, s);
printf("Unsigned: %u, Binary: %x\n", u, u);
return 0;
}
Expected Output:
Signed: -1, Binary: ffffffff
Unsigned: 4294967295, Binary: ffffffff
Explanation: -1 in signed int, with binary representation as all 1s, is interpreted as the maximum unsigned int value when assigned to an unsigned variable.
3. Small Unsigned to Larger Signed Type
Example:
#include <stdio.h>
int main() {
unsigned char uc = 255; // Maximum unsigned char value
int s = uc; // Assigning small unsigned to larger signed
printf("Unsigned char: %u, Binary: %x\n", uc, uc);
printf("Signed int: %d, Binary: %x\n", s, s);
return 0;
}
Expected Output:
Unsigned char: 255, Binary: ff
Signed int: 255, Binary: 000000ff
Explanation: The unsigned char value 255 (0xff) is zero-extended to fit into a larger signed int, maintaining its value.
4. Small Signed to Larger Unsigned Type
Example:
#include <stdio.h>
int main() {
signed char sc = -1; // Negative signed char
unsigned int u = sc; // Assigning small signed to larger unsigned
printf("Signed char: %d, Binary: %x\n", sc, sc);
printf("Unsigned int: %u, Binary: %x\n", u, u);
return 0;
}
Expected Output:
Signed char: -1, Binary: ffffffff
Unsigned int: 4294967295, Binary: ffffffff
Explanation: The signed char -1 (0xff when cast to unsigned for printing) is sign-extended to an unsigned int, becoming the maximum value of unsigned int.
5. Larger Unsigned to Smaller Signed Type
Example:
#include <stdio.h>
int main() {
unsigned int u = 4294967295; // Large unsigned int
signed char sc = u; // Assigning larger unsigned to smaller signed
printf("Unsigned int: %u, Binary: %x\n", u, u);
printf("Signed char: %d, Binary: %x\n", sc, sc);
return 0;
}
Expected Output:
Unsigned int: 4294967295, Binary: ffffffff
Signed char: -1, Binary: ff
Explanation: When the large unsigned int (0xffffffff) is assigned to a smaller signed char, it's truncated to 0xff, which is -1 in signed representation.
These examples show how the binary representations of signed and unsigned integers interact during assignments in C, highlighting the effects of sign and zero extension, and potential issues like truncation.