带for循环的无符号int反向迭代

时间:2011-03-28 11:18:37

标签: c++ loops for-loop overflow iteration

我希望for循环中的iterator变量以#{1}}的形式反向迭代为0,我想不出与unsigned int的类似比较,就像它是i > -1那样。 1}}。

signed int

但这似乎很不清楚,因为它依赖于无符号整数的数值溢出大于10.

也许我只是没有清醒的头脑,但是有什么更好的方法来做到这一点......

免责声明:这只是一个简单的用例,10的上限是微不足道的,它可以是任何内容,for (unsigned int i = 10; i <= 10; --i) { ... } 必须是i

14 个答案:

答案 0 :(得分:31)

您可以使用

for (unsigned int j = n; j-- > 0; ) {}

它从n-1向下迭代到0

答案 1 :(得分:17)

以下是您想要的:

for (unsigned i = 10; i != static_cast<unsigned>(-1); --i)
{
    // ...
}

完美定义,实际上有效。有符号类型的算法由标准准确定义。事实上:

4.7 / 2 (关于转换为无符号类型):

  

如果目标类型是无符号的,则结果值是与源整数一致的最小无符号整数(模2 ^ n,其中n是用于表示无符号类型的位数)

3.9.1 / 4

  

无符号整数,声明为无符号整数,应遵守算术模2 ^ n的定律,其中n是整数特定大小的值表示中的位数

答案 2 :(得分:3)

我的模式通常是......

for( unsigned int i_plus_one = n; i_plus_one > 0; --i_plus_one )
{
    const unsigned int i = i_plus_one - 1;
    // ...
}

答案 3 :(得分:3)

你是否真的从大于std::numeric_limits<int>::max()的某个数字开始迭代?如果没有,我实际上建议您使用普通的int作为循环变量,并static_cast将其unsigned添加到代码中希望无符号的位置>= 0。通过这种方式,您可以使用直观的> -1static_cast条件,一般来说,我希望它比任何未签名的替代方案更具可读性。

{{1}}只是告诉编译器如何操作变量并且根本没有性能影响。

答案 4 :(得分:2)

我可以认为这两个选项可以是强制数字或者是singed数字(例如,可以隐式地与-1进行比较)或者使用循环条件来检查溢出,如下所示:

for(unsigned i=10;i>i-1;--i){ } // i = 10, 9, ... , 1
for(unsigned i=10;i+1>i;--i){ } // i = 10, 9, ... , 1,0

此循环将继续,直到i溢出(意味着它达到零)。请注意,重复的是我迭代1,否则你可能会以无限循环结束。

答案 5 :(得分:1)

我会使用两个变量:

unsigned int start = 10;
for (unsigned int j = 0, i = start; j <= start; ++ j, -- i) {
    // ...
}

你也可以使用while循环:

unsigned int start = 10;
unsigned int i = start + 1;
while (i --) {
    // ...
}

答案 6 :(得分:0)

for(unsigned i = x ; i != 0 ; i--){ ...

如果你想在i == 0时执行循环体并在此之后停止。从i = x+1;

开始 顺便说一句,为什么我必须签名?

答案 7 :(得分:0)

您可以尝试定义以下宏:

#define for_range(_type, _param, _A1, _B1) \
    for (_type _param = _A1, _finish = _B1,\
    _step = static_cast<_type>(2*(((int)_finish)>(int)_param)-1),\
    _stop = static_cast<_type>(((int)_finish)+(int)_step); _param != _stop; \
_param = static_cast<_type>(((int)_param)+(int)_step))

现在你可以使用它了:

for_range (unsigned, i, 10,0)
{
    cout << "backwards i: " << i << endl;
}

它可用于通过无符号,整数,枚举和字符向后和向前迭代:

for_range (char, c, 'z','a')
{
    cout << c << endl;
}

enum Count { zero, one, two, three }; 

for_range (Count, c, zero, three)
{
    cout << "forward: " << c << endl;
}

尽管定义很尴尬,但它的优化得非常好。我在VC ++中查看了反汇编程序。 代码非常有效。不要推迟但是三个for语句:编译器在优化后只会产生一个循环!您甚至可以定义封闭的循环:

unsigned p[4][5];

for_range (Count, i, zero,three)
    for_range(unsigned int, j, 4, 0)
    {   
        p[i][j] = static_cast<unsigned>(i)+j;
    }

你显然无法通过间隙迭代枚举类型。

答案 8 :(得分:0)

我是c ++的新手,我的回答可能真的很愚蠢,但是,我这样做是为了实现这种反向循环;

size_t count = 3;
size_t newCount = 0;
if (count > 0)
    for (size_t i = count - 1; i >= newCount; i--)
    {
        //do your work here

        //and at the end
        if (i == 0)
            break;
    }

,并且有效。由于在下一步执行循环的“ i--”部分,break应该可以正常工作。 您认为这种方式安全吗?

答案 9 :(得分:0)

避免下溢

unsigned int i = n;
while (i !=0){
--i;
...
}

答案 10 :(得分:0)

如果i以1进行迭代,这是避免溢出的简单技巧。

for(unsigned int i = n-1; i+1 >= 1; i--) {;}

如果您希望i进行1次以上的迭代,则

unsigned int d = 2;
for(unsigned int i = n-1; i+d >= d; i-=d) {;}

答案 11 :(得分:0)

for (unsigned int i = 10; i <= 10; --i)

一口气拿下它。

我不想将您已有十年之久的问题回覆给您,但是尝试避免下溢会混淆您最终想要做的事情。

无符号整数的下溢是您可以依赖的明确定义的行为,希望其他程序员可以理解。任何变通方法都将使您要尝试作用的范围变得更难解析,并且可能会使初学者感到困惑,同时如果他们应该以相反的方式将其作为“课程”,则给他们一个不好的榜样循环

答案 12 :(得分:-1)

只需:

int start = 10;
for(unsigned int iPlus1 = start + 1 ; iPlus1 > 0 ; iPlus1--) {
  // use iPlus1 - 1 if you need (say) an array index
  a[iPlus1 - 1] = 123; // ...
}

没有

答案 13 :(得分:-1)

还有一种方法:

for(unsigned i = n-1; i < n ; --i) 
{       
    // Iterates from n-1 to 0
}

Simillarly对于 size_t (无符号整数类型)使用相同的技巧

for(std::size_t i = n-1; i < n ; --i) 
{       
    // Iterates from n-1 to 0
}