答案可能不会使我从专业上受益,但我很想知道:为什么这两个简单的C++循环都不都是无限的?
循环1(无限)

constexpr unsigned short max = USHRT_MAX;
for (signed short ss = 0; ss < max; ++ss);
循环2(非无限)
constexpr unsigned int max = UINT_MAX;
for (signed int si = 0; si < max; ++si);
循环1的输出显示ss递增至SHRT_MAX,然后递增至-SHRT_MAX-1,再递增至-1(或USHRT_MAX),并无限重复该循环。
循环2的输出显示si递增至INT_MAX,然后递增至-INT_MAX - 1,然后递增至-1(或UINT_MAX),然后停止。
有人可以提供我需要的有关这些整数类型如何工作的缺失信息吗(隐式转换,实现奇数等)?

最佳答案

请参阅Does i++ invoke undefined behavior for signed types smaller than int in case of overflow?,以获取对下一段的必要更正。
它的UBsigned short ss = 0; ss < max; ++ss)问题是++ss类似于ss = ss+ 1,这是SHRT_MAX < INT_MAX时分配中实现的定义行为。 ss+1定义明确,但是分配存在争议。无论采用哪种实现,ss都将永远不会达到USHRT_MAX。当SHRT_MAX < USHRT_MAX时,循环是无限的。
signed int si = 0; si < max; ++si是未定义的行为(UB),因为++ss在达到ss < max的限制之前会导致带符号的整数溢出(UB)。
包装++si时将si == INT_MAX的通用UB打包为si == INT_MIN。最终si == -1si < max;就像(unsigned)-1 < max一样,它为false,从而停止了循环。

第二次循环是不确定的。为了肯定地表现,将需要定义的行为。
如果short具有与int相同的大小,则两者均为UB-但仍然不需要表现相同。

推荐:

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

关于c++ - 为什么这两个简单循环都不是无限的?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/63043910/

10-13 08:10