C 2024 (the 2024 edition of the C standard) specifies the binary - operator in clause 6.57. Part of that says:
If both operands have arithmetic type, the usual arithmetic conversions are performed on them.
6.3.2.8 specifies the usual arithmetic conversions with a list of 13 steps, so I will not detail all of them here. The first four apply only when there is a decimal floating-point type, and the fifth only when there is a long double. For your case of double minus short, the sixth step applies:
Otherwise, if the corresponding real type of either operand is double, the other operand is converted, without change of type domain, to a type whose corresponding real type is double.
The real type of double is double,1 so this condition is met, and the short is converted to double. Then the usual arithmetic conversions are done, and the subtraction is performed using double and double.
For your case of short minus long, that sixth step does not apply, and neither does the seventh (about float). The next step says:
Otherwise, if any of the two types is an enumeration, it is converted to its underlying type. Then, the integer promotions are performed on both operands.
Neither short nor long is an enumeration, so that does not apply. Then the integer promotions are performed. 6.3.2.1 specifies the integer promotions. First, the integer promotions apply only to:
An object or expression with an integer type (other than int or unsigned int) whose conversion rank is less than or equal to the rank of int and unsigned int.
A bit-field of type bool, int, signed int, or unsigned int.
Rank is specified in the same clause 12 rules. It is basically an ordering of integer types from narrower to wider. long has greater rank than int and is not a bit-field, so it is not affected by the integer promotions. short has lesser rank than int, so the integer promotions apply to it. The integer promotions are, still in 6.3.2.1:
The value from a bit-field of a bit-precise integer type is converted to the corresponding bit-precise integer type. If the original type is not a bit-precise integer type (6.2.5): if an int can represent all values of the original type (as restricted by the width, for a bit-field), the value is converted to an int; otherwise, it is converted to an unsigned int. These are called the integer promotions. All other types are unchanged by the integer promotions.
short is not a bit-field, and an int can represent all values of short, so short is converted to int.
Now the integer promotions have left us with a long and an int to subtract, and we return to the usual arithmetic conversions.
The next step applies only if the operands are the same type. After that, we have:
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.
long and int are both signed integer types, so the lesser-ranked int is converted to the greater-ranked long. This completes the usual arithmetic conversions, and the subtraction is performed using long and long.
Footnote
1 “Real type” and “type domain” refer to complex number types (as in mathematical complex numbers, with real and imaginary parts). “Real type” means the floating-point type that is used for complex numbers. So the real type of complex double is double. The real type of double is double.
shortandlong…”: It does not depend on the sizes for this case. The integer promotions convertshorttointeven if they are the same size, and the usual arithmetic conversions convert ashort-longpair tolong-longeven ifshortandlongare the same size.