Adding a short int
to a char
results in an int
, which apparently is 4 bytes on your system.
This is a case if "integer promotion". See In a C expression where unsigned int and signed int are present, which type will be promoted to what type? for an explanation. The rules are rather confusing, but the answers there explain it rather well.
Per 6.3.1.8 Usual arithmetic conversions of the C standard, the actual conversion rule is:
If both operands have the same type, then no further conversion is
needed.
Otherwise, if both operands have signed integer types or both have
unsigned integer types, the operand with the type of lesser
integer conversion rank is converted to the type of the operand
with greater rank.
Otherwise, if the operand that has unsigned integer type has
rank greater or equal to the rank of the type of the other
operand, then the operand with signed integer type is
converted to the type of the operand with unsigned integer
type.
Otherwise, if the type of the operand with signed integer type can
represent all of the values of the type of the operand with unsigned
integer type, then the operand with unsigned integer type is
converted to the type of the operand with signed integer type.
Otherwise, both operands are converted to the unsigned
integer type corresponding to the type of the operand with signed
integer type.
The result is 4, because, as @WeatherVane noted in the comments:
5.1.2.3 para 11 EXAMPLE 2 In executing the fragment char c1, c2; /* ... */ c1 = c1 + c2;
the "integer promotions" require that the abstract machine promote the value of each variable to int size and then add the two ints and truncate the sum. But there is no truncation here because the destination is unknown.