2013-07-30 41 views
1

我已经偶然发现了一个持续存在的问题,似乎没有一个合理的解释。这个问题似乎在于内部的for循环进入for (i = size - 1; i >= 0; i--) {etc.}其中size是存储在存储器中缓冲,并i一个文件的大小是一个无符号整数。相反,停车时i == 0的,它将绕 - 从而导致i = 4294967295,造成分段错误。将条件更改为i > 0可解决问题。C for循环行为奇怪

然而,是不是这种奇特?我必须忽略for循环在C中如何操作的一些关键部分。它是否遵循这个方案:初始化,检查条件,增加/减少,检查条件等等?

任何帮助表示赞赏!

+5

“i”总是大于0,因为“i”是无符号整数 –

+3

几乎但不完全@RaghuSrikanthReddy。 – Bart

+0

@巴特的评论是正确的,如果有点不确定。他的意思是,我很确定,'i'总是大于或等于_0,因为'i'是'unsigned int',这几乎不是Raghu所说的。 – ravron

回答

8

一个无符号整数总是>= 0

for (i = size - 1; i >= 0; i--) {etc.} 

是一个无限循环如果iunsigned int

+0

这是否意味着当我被称为与我有价值0它包裹自己? – ckv

+0

@ckv'i'为'0'时,值'i-1'等于'UINT_MAX',这是一个正数量。 – ouah

+0

所以,这就是为什么它不会停止。 '我'永远不会变得消极......我有些时候很愚蠢! :D非常感谢你! – someone

2

让我们来看看i接近0时会发生什么。

  • i == 1:自从i >= 0开始循环正常执行。从i减1。现在i包含0.
  • i == 0:自从i >= 0开始循环正常执行。从i减1。由于i未签名,因此它将环绕。因此,i现在包含4294967295
  • i == 4294967295:循环正常执行,因为i >= 0
  • 等等...

的解决方法是测试其他的东西(如i > 0,喜欢你的例子)或者在每次迭代和循环时增加i,但它小于文件的大小。

+0

它不是首先执行增量/减量操作,然后检查吗?因为在正常的for循环(即'i ++'),当条件是'i <= size'时,最后一次迭代是针对'i == size',并且在出口'i == size + 1'上。 – someone

+0

天使:正确的,但这与我的解释无关,因为条件检查总是跟随一个递减,而递减总是跟着一个条件检查(如果我们方便地忘记了循环体)。 –

+0

是的,事实是我愚蠢地检查了错误的东西!你是对的,它绕了一圈,因为它不会变成负面的,而且变得无限......我修改了它,改为:for(i = size - 1; i someone

1

根据C99标准:

6.2.5类型

9)[...]涉及无符号的操作数可以永远不会溢出,A计算因为 结果不能被表示通过由此产生的无符号整数 类型被减少的模数大于最大的 值,该值可以由结果类型表示。

所以,这里是你的情况会发生什么:

  • i == 1,因此i--结果i == 0
  • i == 0,因此i--产生一个环绕和i == UINT_MAX
  • i == UINT_MAX,因此i--结果在i == UINT_MAX - 1等等。固定你的循环的

一种方法是使用下面的(https://stackoverflow.com/a/665773/676939):

for (i = size; i-- > 0;){ 
    /* yada yada yada */ 
} 

做同样的另一种方式是以下(https://stackoverflow.com/a/665758/676939):

unsigned fake_i; 
for (fake_i = size; fake_i > 0; i--){ 
    unsigned i = fake_i - 1; 
    /* Do something with i */ 
} 
1

无符号类型最重要的位不被视为符号位。 在你的情况下,unsigned int有4bytes(32 bits)

所以,当你递减'0'时,它的做法是的1被添加到0。 这是4294967295并且是最大的值,但是当所有的32位都是1. 因此结果为4294967295

从最大值4294967295(即,当所有32位都是1时)递增 增加此值将使所有低32位为0,32nd位为1。所以,32nd的位溢出到unsigned int的4bytes范围之外。 因此,值变为0。

通常对于无符号类型有一个涡卷从0....MaxValue周围。 当您增加MaxValue以上时,您从0重新输入。 当递减低于0时,您从MaxValue重新输入。

+0

感谢您的回答! :D问题已经解决了,不过... :) – someone