由于整数下溢,while循环是否包含未定义的行为?
首先这是一个Boolean Conversion:
积分,浮点,无作用域枚举,指针,指针到成员类型的prvalue可以转换为bool
类型的prvalue。
值为零(用于积分,浮点和非范围枚举)以及空指针和空指针至成员值变为false
。所有其他值变为true
。
所以不会有整数下溢如果i
正确初始化,将达到0U
和将被强制转换为false
值。
那么编译器有效地在这里做的是:while(static_cast<bool>(i--))
难道编译器都正确的假设,while循环总是true
因为这一点,带着无尽的循环结束了?
这不是无限循环的关键原因是postfix decrement operator返回减量变量的值。它的定义为T operator--(T&, int)
正如之前讨论的那样,编译器将评估该值是否为0U
,作为转换为bool
的一部分。
什么编译器有效地在这里做的是:while(0 != operator--(i, 1))
在你更新你举这个代码作为你的问题的一个动机:
void fn(void)
{
/* write something after this comment so that the program output is 10 */
int a[1] = {0};
int j = 0;
while(a[j] != 5) ++j; /* Search stack until you find 5 */
a[j] = 10; /* Overwrite it with 10 */
/* write something before this comment */
}
经检查,这整个程序已经未定义的行为有只有a
的1个元素,并且它已初始化为0.因此,对于除0
以外的任何索引,a[j]
都在关注数组的末尾。这将持续到找到5
,或者直到操作系统错误,因为程序已从受保护的内存中读取。这与您的循环条件不同,后缀递减运算符返回值为0时将退出,因此不能假定这始终为true
,或者循环将无限持续。
如果i
是signed int
?
上述两种转换均内置于C++。它们都是为所有整数类型定义的,有符号和无符号。所以最终这扩展到:
while(static_cast<bool>(operator--(i, 1)))
它是否包含与数组访问有关的陷阱?
同样,这调用内置的操作中,subscript operator:T& operator[](T*, std::ptrdiff_t)
所以a[i]
是调用operator(a, static_cast<ptrdiff_t>(i))
相当于所以显而易见的后续问题是什么是ptrdiff_t
?它是一个实现定义的整数,但是因为标准的每个实现都负责定义这种类型的转换,所以i
将正确转换。
那么,这是**不是**无限循环。 –
当你运行它时发生了什么? –
没问题,因为'while(0)'是错误的,之后你不关心'i'的值 – MrTux