1

Lets assume the int is the 16-bit type to prevent implicit conversion from short.

long test_1(short x, short y)
{
    return x + y;
}
  1. What are C rules about promoting numbers in this example?
  2. How to protect from modulo arithmetic?
Michas
  • 8,534
  • 6
  • 38
  • 62

1 Answers1

1

The rules are relatively straightforward. The binary + will result in the data type of the "largest" int. If you have two operands of the same type, the result will be the same type.

The expression

return x+y

is evaluated in two steps. In the first, the result of x+y is computed. This is a short (as in your first declaration). then it is cast to the type of the function.

If you want to avoid the overflow, you need to cast the operands of plus to the desired type:

return ((long)x) + y

I have oveparenthesized for clarity.

dmg
  • 4,231
  • 1
  • 18
  • 24
  • I tested OP's first code in MSVC with `test_1(32767, 32767);` and it returned the correct result `65534`. Although, `short` is only required to be *at least* 16 bits, it *is* in my compiler. – Weather Vane Oct 30 '16 at 19:00
  • @WeatherVane What ABI of MSVC? – Michas Oct 30 '16 at 19:04
  • 1
    @Michas AFAIK integral types smaller than `int` are promoted to `int` before the calculation. Please [see accepted answer](http://stackoverflow.com/questions/24371868/why-must-a-short-be-converted-to-an-int-before-arithmetic-operations-in-c-and-c) is the best I can find at short notice. – Weather Vane Oct 30 '16 at 19:08
  • @WeatherVane. No For example char c,d; c+d are not converted to int. They remain char. – dmg Oct 30 '16 at 19:09
  • Then why did my `short` multiplication not overflow? – Weather Vane Oct 30 '16 at 19:10
  • I would test the size of the short to make sure it is not the same as the int. Compute the sizeof(short) and sizeof(int). THe standard says that sizeof(short) <= sizeof(int) <= size(long) <= sizeof(long long). – dmg Oct 30 '16 at 19:12
  • Please then explain why `char c = 127; int i = c * c; printf("%d\n", i);` outputs `16129`? – Weather Vane Oct 30 '16 at 19:12
  • 1
    It is not the standard itself but please [see this](https://www.securecoding.cert.org/confluence/display/c/INT02-C.+Understand+integer+conversion+rules) *"Integer types smaller than int are promoted when an operation is performed on them. If all values of the original type can be represented as an int, the value of the smaller type is converted to an int; otherwise, it is converted to an unsigned int."* – Weather Vane Oct 30 '16 at 19:15
  • I'll be damned. You are right. See: http://stackoverflow.com/questions/17882326/is-unsigned-char-always-promoted-to-int – dmg Oct 30 '16 at 19:17
  • And then *"Integer promotions require the promotion of each variable (c1 and c2) to int size. The two int values are added, and the sum is truncated to fit into the char type. Integer promotions are performed to avoid arithmetic errors resulting from the overflow of intermediate values:"* – Weather Vane Oct 30 '16 at 19:17
  • @WeatherVane I ask about other rules of promotions. For 16-bit `int` there is no implicit conversion of `short`. – Michas Oct 31 '16 at 08:03
  • @Michas how could there be, if already 16 bit? – Weather Vane Oct 31 '16 at 08:20