For 循环退出条件(size_t vs. int)
For Loop Exit Condition (size_t vs. int)
当我将以下内容放入我的程序中时:
for (size_t i = VectorOfStructs.size()-1; i > 0; i--)
它工作正常,但 "i" 永远不会等于 0。
因此,我无法访问第一个元素 (VectorOfStructs[0])。
如果我把它改成:
for (size_t i = VectorOfStructs.size()-1; i > -1; i--)
程序甚至没有进入for循环!但是,如果我将其更改为以下内容:
for (int i = VectorOfStructs.size()-1; i > -1; i--)
它完全符合我的要求(遍历所有元素)。
所以,我的问题是:
(A)为什么第二个代码片段执行失败?
(B) 为什么第三个代码片段相应地执行而第二个代码片段没有执行?
任何见解将不胜感激!
第二个例子使用size_t
作为i
的类型,这是一个unsigned类型,因此它永远不能有负值;这也意味着它不能与 -1
进行正确比较
但是 (int)-1
被位表示为 0xFFFFFFFF
,这代表 size_t
相当大的数字 (2^32-1
)。 i>0xFFFFFFFF
永远不可能为真,因为 0xFFFFFFF
是 size_t
可以容纳的最大值。
第三个示例使用 signed int
(允许负数,因此测试成功)。
这个应该有效:
for (size_t i = VectorOfStructs.size(); i-- > 0;) {
use(VectorOfStructs[i]);
}
size_t
是无符号类型,所以 -1
是 size_t
可以取的最大值。在第二个代码段中,size_t
不能大于此最大值,因此不会进入循环。
另一方面,int
是有符号类型,因此与 -1
的比较如您所料。
Why does the 2nd code snippet fail to execute?
size_t
是无符号的,因此根据定义它永远不会为负数。所以你的循环条件总是正确的。变量"wraps around"到最大值。
在第二个中,您将变量 'i' 与 -1 进行比较,此处它的类型为 size_t 并且大小不能为负数,因此失败。
第三个,'i'是整数类型,整数的范围是-32568到+32567(对于系统中的int=2字节)
整体size_t
变量不能有负值,因为物理内存会在系统中存在
所有循环都向前,即使是向后循环。
你想要的是:
for (std::size_t i = 0, e = VectorOfStructs.size(); i != e; ++i)
{
std::size_t const ri = e - i - 1;
// use "VectorOfStructs[ri]"
}
或更好:
for (auto rit = VectorOfStructs.rbegin(); rit != VectorOfStructs.rend(); ++rit)
{
// use "*rit"
}
(你的第二个片段失败,因为 i
是无符号的,所以 -1
被转换为与 i
相同的类型并成为最大可表示值,所以比较总是正确的.相比之下,i
在第三个片段中签名。)
Int 和 size_t 都是整数类型,但 int 可以包含负数和正数。
int 范围从 -2^31 -1 到 2^31 -1 而 size_t 范围从 0 到 2^32 -1
现在,当你写类似 int a = -1 的东西时,它确实是 -1 但当你用 size_t 这样做时,你会得到 max int 2^32 -1
所以在第二个片段中没有 size_t 值会超过 -1 因为它真的是 2^32 -1
在第 3 个片段中,比较的类型是 int,当将 int 与 -1 进行比较时,它会将其视为 -1,因此它会按您计划的方式执行
当编译器看到 i > -1
并注意到子表达式 i
和 -1
具有不同的类型时,它会将它们都转换为 通用类型.如果这两种类型(std::size_t
和 int
)具有相同的位数(您的编译器似乎就是这种情况),则常见类型是无符号类型 (std::size_t
)。所以表达式结果等价于 i > (std::size_t)-1
。但是当然 (std::size_t)-1
是一个 size_t
的最大可能值,所以比较总是假的。
大多数编译器都会发出警告,指出出于此类原因,比较始终为真或始终为假。
每当您比较 'signed' 和 'unsigned' 时,'signed' 值首先会转换为 'unsigned'。这涵盖了 (#1) 和 (#2),'unsigned(0-1)' 和 'some unsigned' > 'unsigned max'.
有问题
但是,通过强制进行 'signed'/'signed' 比较(#3)使其工作,您失去了 'unsigned' 范围的 1/2。
你可以这样做:
for(size_t n = vector.size(); n; /* no -- here */ ) {
--n;
// vector[n];
}
注意:unsigned(-1) 在许多系统上是最大的无符号整数值。
当我将以下内容放入我的程序中时:
for (size_t i = VectorOfStructs.size()-1; i > 0; i--)
它工作正常,但 "i" 永远不会等于 0。 因此,我无法访问第一个元素 (VectorOfStructs[0])。
如果我把它改成:
for (size_t i = VectorOfStructs.size()-1; i > -1; i--)
程序甚至没有进入for循环!但是,如果我将其更改为以下内容:
for (int i = VectorOfStructs.size()-1; i > -1; i--)
它完全符合我的要求(遍历所有元素)。
所以,我的问题是:
(A)为什么第二个代码片段执行失败?
(B) 为什么第三个代码片段相应地执行而第二个代码片段没有执行?
任何见解将不胜感激!
第二个例子使用size_t
作为i
的类型,这是一个unsigned类型,因此它永远不能有负值;这也意味着它不能与 -1
但是 (int)-1
被位表示为 0xFFFFFFFF
,这代表 size_t
相当大的数字 (2^32-1
)。 i>0xFFFFFFFF
永远不可能为真,因为 0xFFFFFFF
是 size_t
可以容纳的最大值。
第三个示例使用 signed int
(允许负数,因此测试成功)。
这个应该有效:
for (size_t i = VectorOfStructs.size(); i-- > 0;) {
use(VectorOfStructs[i]);
}
size_t
是无符号类型,所以 -1
是 size_t
可以取的最大值。在第二个代码段中,size_t
不能大于此最大值,因此不会进入循环。
另一方面,int
是有符号类型,因此与 -1
的比较如您所料。
Why does the 2nd code snippet fail to execute?
size_t
是无符号的,因此根据定义它永远不会为负数。所以你的循环条件总是正确的。变量"wraps around"到最大值。
在第二个中,您将变量 'i' 与 -1 进行比较,此处它的类型为 size_t 并且大小不能为负数,因此失败。
第三个,'i'是整数类型,整数的范围是-32568到+32567(对于系统中的int=2字节)
整体size_t
变量不能有负值,因为物理内存会在系统中存在
所有循环都向前,即使是向后循环。
你想要的是:
for (std::size_t i = 0, e = VectorOfStructs.size(); i != e; ++i)
{
std::size_t const ri = e - i - 1;
// use "VectorOfStructs[ri]"
}
或更好:
for (auto rit = VectorOfStructs.rbegin(); rit != VectorOfStructs.rend(); ++rit)
{
// use "*rit"
}
(你的第二个片段失败,因为 i
是无符号的,所以 -1
被转换为与 i
相同的类型并成为最大可表示值,所以比较总是正确的.相比之下,i
在第三个片段中签名。)
Int 和 size_t 都是整数类型,但 int 可以包含负数和正数。 int 范围从 -2^31 -1 到 2^31 -1 而 size_t 范围从 0 到 2^32 -1
现在,当你写类似 int a = -1 的东西时,它确实是 -1 但当你用 size_t 这样做时,你会得到 max int 2^32 -1
所以在第二个片段中没有 size_t 值会超过 -1 因为它真的是 2^32 -1
在第 3 个片段中,比较的类型是 int,当将 int 与 -1 进行比较时,它会将其视为 -1,因此它会按您计划的方式执行
当编译器看到 i > -1
并注意到子表达式 i
和 -1
具有不同的类型时,它会将它们都转换为 通用类型.如果这两种类型(std::size_t
和 int
)具有相同的位数(您的编译器似乎就是这种情况),则常见类型是无符号类型 (std::size_t
)。所以表达式结果等价于 i > (std::size_t)-1
。但是当然 (std::size_t)-1
是一个 size_t
的最大可能值,所以比较总是假的。
大多数编译器都会发出警告,指出出于此类原因,比较始终为真或始终为假。
每当您比较 'signed' 和 'unsigned' 时,'signed' 值首先会转换为 'unsigned'。这涵盖了 (#1) 和 (#2),'unsigned(0-1)' 和 'some unsigned' > 'unsigned max'.
有问题但是,通过强制进行 'signed'/'signed' 比较(#3)使其工作,您失去了 'unsigned' 范围的 1/2。
你可以这样做:
for(size_t n = vector.size(); n; /* no -- here */ ) {
--n;
// vector[n];
}
注意:unsigned(-1) 在许多系统上是最大的无符号整数值。