C++ 中的无符号整数for 循环

发布于 2024-12-29 08:40:31 字数 711 浏览 8 评论 0原文

我在 Stackoverflow 上做了一些关于 C++ 中使用无符号整数而不是有符号整数的反向 for 循环的研究。但我仍然不明白为什么会出现问题(参见 Unsigned int 反向迭代for 循环)。为什么下面的代码会产生分段错误?

#include <vector>
#include <iostream>
using namespace std;

int main(void)
{
    vector<double> x(10);

    for (unsigned int i = 9; i >= 0; i--)
    {
        cout << "i= " << i << endl;
        x[i] = 1.0;
    }

    cout << "x0= " << x[0] << endl;

    return 0;
}

我知道问题在于索引 i 何时等于零,因为存在溢出之类的情况。但我认为无符号整数可以取零值,不是吗?现在如果我用有符号整数替换它,绝对没有问题。

有人可以向我解释使用无符号整数的反向循环背后的机制吗?

非常感谢!

I have made some research on Stackoverflow about reverse for loops in C++ that use an unsigned integer instead of a signed one. But I still do NOT understand why there is a problem (see Unsigned int reverse iteration with for loops). Why the following code will yield a segmentation fault?

#include <vector>
#include <iostream>
using namespace std;

int main(void)
{
    vector<double> x(10);

    for (unsigned int i = 9; i >= 0; i--)
    {
        cout << "i= " << i << endl;
        x[i] = 1.0;
    }

    cout << "x0= " << x[0] << endl;

    return 0;
}

I understand that the problem is when the index i will be equal to zero, because there is something like an overflow. But I think an unsigned integer is allowed to take the zero value, isn't it? Now if I replace it with a signed integer, there is absolutely no problem.

Does somebody can explain me the mechanism behind that reverse loop with an unsigned integer?

Thank you very much!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

拧巴小姐 2025-01-05 08:40:31

这里的问题是无符号整数永远不会是负数。

因此,循环测试:

i >= 0

将始终为真。这样你就得到了一个无限循环。

当它低于零时,它会返回到最大值无符号值。

因此,您也将访问 x[i] 越界

对于有符号整数来说这不是问题,因为它只会变成负数,从而失败 i >= 0

因此,如果您想使用无符号整数,您可以尝试以下可能性之一:

for (unsigned int i = 9; i-- != 0; )

for (unsigned int i = 9; i != -1; i--)

这两个是由 GManNickG 和 AndreyT 从评论中建议的。


这是我原来的 3 个版本:

for (unsigned int i = 9; i != (unsigned)0 - 1; i--)

for (unsigned int i = 9; i != ~(unsigned)0; i--)

for (unsigned int i = 9; i != UINT_MAX; i--)

The problem here is that an unsigned integer is never negative.

Therefore, the loop-test:

i >= 0

will always be true. Thus you get an infinite loop.

When it drops below zero, it wraps around to the largest value unsigned value.

Thus, you will also be accessing x[i] out-of-bounds.

This is not a problem for signed integers because it will simply go negative and thus fail i >= 0.

Thus, if you want to use unsigned integers, you can try one of the following possibilities:

for (unsigned int i = 9; i-- != 0; )

and

for (unsigned int i = 9; i != -1; i--)

These two were suggested by GManNickG and AndreyT from the comments.


And here's my original 3 versions:

for (unsigned int i = 9; i != (unsigned)0 - 1; i--)

or

for (unsigned int i = 9; i != ~(unsigned)0; i--)

or

for (unsigned int i = 9; i != UINT_MAX; i--)
不交电费瞎发啥光 2025-01-05 08:40:31

问题是,您的循环允许 i 低至零,并且仅当 i 小于 0 时才期望退出循环。由于 i 是无符号的,因此它永远不会小于 0。它会滚动到 2^32-1 。这大于向量的大小,因此会导致段错误。

The problem is, your loop allows i to be as low as zero and only expects to exit the loop if i is less than 0. Since i is unsigned, it can never be less than 0. It rolls over to 2^32-1. That is greater than the size of your vector and so results in a segfault.

淡淡の花香 2025-01-05 08:40:31

无论 unsigned int i 的值是多少,i >= 0 始终为真,因此您的 for 循环永远不会结束。

换句话说,如果在某个时刻 i 为 0 并且您将其递减,它仍然保持非负数,因为它包含一个巨大的数字,可能是 4294967295(即 232-1)。

Whatever the value of unsigned int i it is always true that i >= 0 so your for loop never ends.

In other words, if at some point i is 0 and you decrement it, it still stays non-negative, because it contains then a huge number, probably 4294967295 (that is 232-1).

手心的温暖 2025-01-05 08:40:31

问题就在这里:

for (unsigned int i = 9; i >= 0; i--) 

您以 unsigned int 的值 9 开始,并且您的退出定义是 i >= 0 并且这将始终为真。 (无符号整数永远不会为负!!!)。因此,你的循环将重新开始(无限循环,因为 i=0 那么 -1 变为 max uint)。

The problem is here:

for (unsigned int i = 9; i >= 0; i--) 

You are starting with a value of 9 for an unsigned int and your exit definition is i >= 0 and this will be always true. (unsigned int will never be negative!!!). Because of this your loop will start over (endless loop, because i=0 then -1 goes max uint).

神魇的王 2025-01-05 08:40:31

正如您所说,无符号数减少到零以下(发生在循环的最后一步之后)会产生溢出,数字会回绕到其最大值,因此我们最终会陷入无限循环。

有人可以向我解释使用无符号整数的反向循环背后的机制吗?

我对于带有索引的反向循环的首选方法是这样的:

for (unsigned int i = 9; i > 0; --i) {
    cout << "i= " << x[i - 1] << endl;
}

这就是为什么,因为它与正常循环的映射最接近:

for (unsigned int i = 0; i < 9; ++i) {
    cout << "i= " << x[i] << endl;
}

如果那么您需要多次访问索引元素并且您不想连续写入 [i - 1],您可以添加类似这样的内容作为循环中的第一行:

auto& my_element = my_vector[i - 1];

As you said a decrease of an unsigned below zero, which happens right after the last step of the loop, creates an overflow, the number wraps around to its maximum value and thus we end up with an infinite loop.

Does somebody can explain me the mechanism behind that reverse loop with an unsigned integer?

My preferred method for a reverse loop with an index is this:

for (unsigned int i = 9; i > 0; --i) {
    cout << "i= " << x[i - 1] << endl;
}

and that is why because it maps most closely to the normal loop equivalent:

for (unsigned int i = 0; i < 9; ++i) {
    cout << "i= " << x[i] << endl;
}

If then you need to access the indexed element multiple times and you don't want to continuously write [i - 1], you can add something like this as the first line in the loop:

auto& my_element = my_vector[i - 1];
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文