为什么这会创建一个无限的负奇数列表?
Why does this create an infinite list of negative odd numbers?
如果 i=1,为什么以下指令会创建一个无限的负数列表(-1、-3、-5、...)?
while (i--)
printf("\n%i", --i);
原因是 i--
是一个 post 递减运算符。意思是,i 的值用在表达式中,然后是表达式本身的求值。这会导致您比较中的 i 值与打印语句中存在的值不同,从而形成无限循环。
i--
Post 递减操作,告诉该值被使用
首先是表达式求值。
--i
预减操作告诉表达式是
首先求值,然后使用表达式的结果。
i = 1 // 1
while (i--) // value of 'i--' is 1 is true; side-effect i = 0
printf("\n%i", --i); // print value of '--i' ie -1, side-effect i = -1
while (i--) // value of 'i--' is -1 is true; side-effect i = -2
printf("\n%i", --i); // print value of '--i' ie -3, side-effect i = -3
while (i--) // value of 'i--' is -3 is true; side-effect i = -4
printf("\n%i", --i); // print value of '--i' ie -5, side-effect i = -5
...
请注意,上面的副作用可能发生在对表达式其余部分求值之前或之后(甚至期间)。
while
条件使用post递减。这意味着它测试 i
的原始值,即 1
,然后将值递减为 0
。由于 1
是真实的,它进入循环。
在循环内,您打印 --i
。这是预递减,因此它将 i
设置为 -1
,并打印该值。
在下一次迭代中,同样的事情发生了。它测试 -1
,这是真实的,将它递减到 -2
,进入循环体,将它递减到 -3
,然后打印出来。
最终,当 i
溢出到最小负数以下时,您的代码将 运行 变成未定义的行为。在大多数实现中,它会循环并继续相同的进程,但实际行为并不特定于语言。
在每次迭代中,i 递减 2 次,这就是系列 1、-1、-3 等。始终为正值,这会导致无限循环。如果您选择 i=2,那么系列将为 2、0,仅此而已。得到零后 while 循环将退出。
i
似乎是 int
类型,并且是一个带符号的整数,它也涵盖负数范围。
标准规定 int
需要至少能够表示 −32767
到 32767
的范围。
如果你减少它,值可以下降到 INT_MIN
。
如果在到达 INT_MIN
的边界后减小该值,则行为未定义。
i
在每次迭代中递减 2
,因此输出显示减少 2er 步。
循环是否无限取决于实现如何处理 INT_MIN
之后的递减。
只要 i
不为零,while
条件就始终为真,这里就是这种情况,因为 i
在第一次迭代时递减 2,并且此后 i
为负。
因为您从奇数 2 中减去 2,所以在大多数实现中它永远不会为零。
while (i--)
if(i & 1) printf("\n%i", i);
会在某个时候停止。
没什么特别的。你有负数的 i,它在开始时等于 1(然后是 -1,-3,-5,...),因为你将变量 i 递减了两次。首先,您在条件表达式中执行此操作:“while(i--)”。在它之后,它发生在 while 代码块中:"printf("\n%i", --i);"。最后,由于您正在使用 while 循环,它一次又一次地减少 2。
如果 i=1,为什么以下指令会创建一个无限的负数列表(-1、-3、-5、...)?
while (i--)
printf("\n%i", --i);
原因是 i--
是一个 post 递减运算符。意思是,i 的值用在表达式中,然后是表达式本身的求值。这会导致您比较中的 i 值与打印语句中存在的值不同,从而形成无限循环。
i--
Post 递减操作,告诉该值被使用 首先是表达式求值。--i
预减操作告诉表达式是 首先求值,然后使用表达式的结果。
i = 1 // 1
while (i--) // value of 'i--' is 1 is true; side-effect i = 0
printf("\n%i", --i); // print value of '--i' ie -1, side-effect i = -1
while (i--) // value of 'i--' is -1 is true; side-effect i = -2
printf("\n%i", --i); // print value of '--i' ie -3, side-effect i = -3
while (i--) // value of 'i--' is -3 is true; side-effect i = -4
printf("\n%i", --i); // print value of '--i' ie -5, side-effect i = -5
...
请注意,上面的副作用可能发生在对表达式其余部分求值之前或之后(甚至期间)。
while
条件使用post递减。这意味着它测试 i
的原始值,即 1
,然后将值递减为 0
。由于 1
是真实的,它进入循环。
在循环内,您打印 --i
。这是预递减,因此它将 i
设置为 -1
,并打印该值。
在下一次迭代中,同样的事情发生了。它测试 -1
,这是真实的,将它递减到 -2
,进入循环体,将它递减到 -3
,然后打印出来。
最终,当 i
溢出到最小负数以下时,您的代码将 运行 变成未定义的行为。在大多数实现中,它会循环并继续相同的进程,但实际行为并不特定于语言。
在每次迭代中,i 递减 2 次,这就是系列 1、-1、-3 等。始终为正值,这会导致无限循环。如果您选择 i=2,那么系列将为 2、0,仅此而已。得到零后 while 循环将退出。
i
似乎是 int
类型,并且是一个带符号的整数,它也涵盖负数范围。
标准规定 int
需要至少能够表示 −32767
到 32767
的范围。
如果你减少它,值可以下降到 INT_MIN
。
如果在到达 INT_MIN
的边界后减小该值,则行为未定义。
i
在每次迭代中递减 2
,因此输出显示减少 2er 步。
循环是否无限取决于实现如何处理 INT_MIN
之后的递减。
只要 i
不为零,while
条件就始终为真,这里就是这种情况,因为 i
在第一次迭代时递减 2,并且此后 i
为负。
因为您从奇数 2 中减去 2,所以在大多数实现中它永远不会为零。
while (i--)
if(i & 1) printf("\n%i", i);
会在某个时候停止。
没什么特别的。你有负数的 i,它在开始时等于 1(然后是 -1,-3,-5,...),因为你将变量 i 递减了两次。首先,您在条件表达式中执行此操作:“while(i--)”。在它之后,它发生在 while 代码块中:"printf("\n%i", --i);"。最后,由于您正在使用 while 循环,它一次又一次地减少 2。