TransWikia.com

Why aren't both of these simple loops infinite?

Stack Overflow Asked by grahfoster on December 1, 2021

The answer to this will probably not benefit me in any way professionally, but I’m keen to know: why aren’t these two simple C++ loops both infinite?

Loop 1 (infinite)

constexpr unsigned short max = USHRT_MAX;
for (signed short ss = 0; ss < max; ++ss);

Loop 2 (not infinite)

constexpr unsigned int max = UINT_MAX;
for (signed int si = 0; si < max; ++si);

Output for loop one shows that ss increments to SHRT_MAX, then to –SHRT_MAX – 1, then to -1 (or USHRT_MAX), and repeats that loop infinitely.

Output for loop two shows that si increments to INT_MAX, then to –INT_MAX - 1, then to -1 (or UINT_MAX), and then stops.

Can someone supply the missing information I need about how these integer types work, be it implicit conversion, implementation oddities, etc?

2 Answers

As they said this is undefined behavior, but in your case it might be that comparison values are converted to int thus second one is infinite, since it does not co to USHRT_MAX (65535) instead it goes to SHORT_MAX and overflows to negative values. See this:

5/9: (Expressions)

Many binary operators that expect operands of arithmetic or enumeration type cause conversions and yield result types in a similar way. The purpose is to yield a common type, which is also the type of the result. This pattern is called the usual arithmetic conversions, which are defined as follows:

  • If either operand is of type long double, the other shall be converted to long double.
  • Otherwise, if either operand is double, the other shall be converted to double.
  • Otherwise, if either operand is float, the other shall be converted to float.
  • Otherwise, the integral promotions (4.5) shall be performed on both operands.54)
  • Then, if either operand is unsigned long the other shall be converted to unsigned long.
  • Otherwise, if one operand is a long int and the other unsigned int, then if a long int can represent all the values of an unsigned int, the unsigned int shall be converted to a long int; otherwise both operands shall be converted to unsigned long int.
  • Otherwise, if either operand is long, the other shall be converted to long.
  • Otherwise, if either operand is unsigned, the other shall be converted to unsigned.

4.7/2: (Integral conversions)

If the destination type is unsigned, the resulting value is the least unsigned integer congruent to the source integer (modulo 2n where n is the number of bits used to represent the unsigned type). [Note: In a two’s complement representation, this conversion is conceptual and there is no change in the bit pattern (if there is no truncation). ]

Answered by user5550963 on December 1, 2021

See Does i++ invoke undefined behavior for signed types smaller than int in case of overflow? for a needed correction to the next paragraph.

Its UB

signed short ss = 0; ss < max; ++ss) problem is that ++ss is like ss = ss+ 1 and that is implementation defined behavior in the assignment when SHRT_MAX < INT_MAX. ss+1 is well defined, but the assignment is at issue. Whatever the implementation, ss will never reach USHRT_MAX. When SHRT_MAX < USHRT_MAX, the loop is infinite.


signed int si = 0; si < max; ++si is undefined behavior (UB) as ++ss incurs signed integer overflow (which is UB) before reaching the limit of ss < max.
A common UB of ++si when si == INT_MAX is to wrap, making si == INT_MIN. Eventually si == -1 and si < max; is like (unsigned)-1 < max which is false, stopping the loop.

Why aren't both of these simple loops infinite?

The 2nd loop is undefined. For to certainly behave would require defined behavior.

Had short had the same size as int, both would be UB - yet still would not be required to behave the same.


Recommend:

constexpr unsigned short max = USHRT_MAX;
//   vv
for (unsigned short ss = 0; ss < max; ++ss);

and

constexpr unsigned int max = UINT_MAX;
//   vv
for (unsigned int si = 0; si < max; ++si);

Answered by chux - Reinstate Monica on December 1, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP