我的代码是:
#include<stdio.h>
main() {
short int i=0;
for(i<=5 && i>=-1; ++i; i>0)
printf("%d, ",i);
return 0;
}
输出:-
我不知道它从哪里开始但按顺序结束
..., -4, -3, -2, -1
你能帮我理解这个代码片段的工作原理吗?
for(i<=5 && i>=-1; ++i; i>0)
相当于:
for(; ++i;)
因为i<=5 && i>=-1
andi > 0
表达式没有副作用。
现在控制表达式是++i
,这意味着循环被执行,直到++i
被评估为0
。
i
是一个short
对象,所以++i
等价于i = (int) i + 1
.
当(int) i + 1
转换为short
objecti
并且值在 a 中不可表示时short
,转换是实现定义的(参见 C99,6.3.1.3p3)。
在您的实现中,行为是当值在 a 中不可表示时short
,它只是环绕并变成一个巨大的负值 ( SHRT_MIN
)。循环重复执行,直到++i
控制表达式为0
。
这是一个格式错误的句子,在语法上是正确的。它没有有意义的初始化(例如 i=0),而是有一个评估为真的语句。作为比较,它只增加变量 i 并在 i 达到零时结束。每次成功迭代后要执行的 end 语句什么也不做。
该语句的工作部分等价于 while (++i) printf("%d",i); 和(由于 2 的补数的性质,它从 1,2,3,4,..., 32766,32767 循环,并换行为负数 -32768, -32767, ..., -3,-2 ,-1. (并在 i == 0 的下一次迭代中停止)
编辑:循环可能永远持续下去,直到满足条件 i==0 。计算机中的整数计算通常以模 2^16 或模 2^32、模 2^64 等计算。恰好将 16 位数字中可用的 65536 个不同值的范围映射到 2 个范围非常方便:0 ...32767 和 32768...65535,其中后半部分可以解释为正整数 [无符号] 或值为 (x-65536) 的负整数。c 语言关键字signed要求计算机这样做。
在
for(i<=5 && i>=-1; ++i; i>0)
这个
i<=5 && i>=-1
意味着真实,因为0 <= 5 and 0 >= -1
为什么你得到-2,-1?这是缓冲区溢出。当您将 1 添加到 MAX_INT 时,您将得到负数
01111
加 1
10000
第一位是负位(1 - 数字为负,0 - 为正)
看看这个http://en.wikipedia.org/wiki/Two%27s_complement
您也可以尝试修改int
为unsigned int
输出是
1, 2, 3, 4, 5,
....
-5, -4, -3, -2, -1
您可以通过以下方式检查
program.exe > out.txt
您将for
循环中的子句混淆了,这导致您一直计数到最大短整数值。当你把它加 1 时,它会循环到最小的短整数值,一个负数,然后继续计数直到它达到 0,此时循环最终停止。它循环的原因是整数通常存储在二进制补码中,并且大多数 CPU 和编译器在溢出时不会做任何特殊的事情。他们只是继续添加,即使结果没有意义。在二进制补码中,最大整数值表示为0111...
; 当你加 1 时,你得到1000...
,这是最小的负整数。
在 C for 循环中,表达式是.for(initializer; condition; update) body
初始化程序在开始时运行一次,以初始化任何变量。由于您只是在进行一些比较,因此它在您的循环中基本上什么都不做。
该条件在每次迭代之前运行一次,在运行该迭代之前,以测试循环是否应该继续。你的条件是++i
。这会增加i
(加一)并返回结果。因此,在第一次通过时,i
从 开始0
,将其递增到1
,for
循环使用该值来决定循环是否应该继续。除此以外的任何数字0
在 C 中都被认为是“真”,因此循环继续;它会一直运行,直到你到达i
is的点-1
,所以增加它会给你留下0
,这是一个错误的值。
更新表达式在每次迭代后运行一次,在正文之后,以更新您可能需要继续迭代的任何变量。您只是在这里进行比较,它不使用该值,因此您基本上什么都不做。
最后,您的 for 循环与以下内容基本相同:
for (;++i;)
printf("%d, ",i);
这也与以下内容相同:
while (++i)
printf("%d, ",i);
您可能的意思是:
for (i = 0; i <= 5; ++i)
printf("%d, ",i);