我的代码是:
#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
你可以帮我理解这段代码片段的工作原理吗?
答案 0 :(得分:2)
for(i<=5 && i>=-1; ++i; i>0)
相当于:
for(; ++i;)
因为i<=5 && i>=-1
和i > 0
表达式没有副作用。
现在控制表达式为++i
,这意味着循环执行直到++i
被评估为0
。
i
是short
个对象,因此++i
相当于i = (int) i + 1
。
当(int) i + 1
转换为short
对象i
并且该值无法在short
中表示时,转换是实现定义的(请参阅C99,6.3.1.3p3 )。
在您的实现中,行为是当值short
中无法表示时,它只是环绕并变为巨大的负值(SHRT_MIN
)。循环重复执行,直到++i
控制表达式为0
。
答案 1 :(得分:0)
这是一个格式错误的句子,在句法上是正确的。 它不是有意义的初始化(例如i = 0),而是有一个计算结果为true的语句。作为比较,当i达到零时,它仅增加变量i并结束。每次成功迭代后要执行的结束语句都不执行任何操作。
声明的工作部分等同于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,其中后一部分可以解释为正整数[unsigned]或者为负整数,其值为(x-65536)。 c语言关键字已签名要求计算机执行此操作。
答案 2 :(得分:0)
in
for(i<=5 && i>=-1; ++i; i>0)
此
i<=5 && i>=-1
表示true,因为0 <= 5 and 0 >= -1
为什么你得到-2,-1? 这是缓冲区溢出。当您向MAX_INT添加1时,您将获得负数
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
答案 3 :(得分:0)
您的for
循环中的子句会混淆,这会导致您一直计入最大的短整数值。当你加1时,它会循环到最小的短整数值,一个负数,然后继续计数直到它变为0,此时循环最终停止。它循环的原因是因为整数通常存储在two's complement中,并且大多数CPU和编译器在溢出时不做任何特殊操作;他们只是不断添加,即使结果没有意义。在二进制补码中,最大整数值表示为0111...
;当你加1时,得到1000...
,这是最小的负整数。
在C for循环中,表达式为for(initializer; condition; update) body
。
初始化程序在开头运行一次,以初始化任何变量。由于你只是进行一些比较,它在你的循环中基本上什么都不做。
条件每次迭代运行一次,然后运行该迭代,以测试循环是否应该继续。您的条件是++i
。这会增加i
(向其添加一个)并返回结果。因此,在第一次传递时,i
从0
开始,将其递增到1
,for
循环使用该值来决定循环是否应该继续。除0
之外的任何数字在C中都被视为“真”,因此循环继续;蚂蚁它一直持续到i
为-1
为止,因此递增它会留下0
,这是一个假值。
update 表达式在主体之后每次迭代运行一次,以更新可能需要继续迭代的任何变量。你只是在这里进行比较,因为它没有使用该值,所以你基本上什么都不做。
最后,你的for循环基本上与:
相同for (;++i;)
printf("%d, ",i);
这也与:
相同while (++i)
printf("%d, ",i);
你可能的意思是:
for (i = 0; i <= 5; ++i)
printf("%d, ",i);