Elp*_*rto 41 c int unsigned for-loop
这是一个相当愚蠢的问题,但为什么int常用而不是unsigned int在C或C++中为数组定义for循环时?
for(int i;i<arraySize;i++){}
for(unsigned int i;i<arraySize;i++){}
Run Code Online (Sandbox Code Playgroud)
我认识到int在进行数组索引以外的操作时使用的好处以及使用C++容器时迭代器的好处.是不是因为在循环数组时无关紧要?或者我应该一起避免它并使用不同的类型,如size_t?
650*_*502 36
int从索引数组的逻辑角度来看,使用更为正确.
unsigned C和C++中的语义并不真正意味着"不是负面的",而是更像是"bitmask"或"modulo integer".
要理解为什么unsigned不是"非负"数字的好类型,请考虑
显然,上述短语都没有任何意义......但它是C和C++ unsigned语义确实有效的方式.
实际上使用unsigned容器大小的类型是C++的设计错误,不幸的是我们现在注定要永远使用这个错误的选择(为了向后兼容).你可能喜欢这个名字"unsigned",因为它类似于"非负面",但名称是无关紧要的,重要的是语义......并且unsigned与"非负面"相差甚远.
因此,当在矢量上编码大多数循环时,我个人首选的形式是:
for (int i=0,n=v.size(); i<n; i++) {
...
}
Run Code Online (Sandbox Code Playgroud)
(当然假设矢量的大小在迭代期间没有变化,而且我实际上需要体内的索引,否则for (auto& x : v)...更好).
这种unsigned尽快逃避并使用普通整数的优点是避免了unsigned size_t设计错误导致的陷阱.例如考虑:
// draw lines connecting the dots
for (size_t i=0; i<pts.size()-1; i++) {
drawLine(pts[i], pts[i+1]);
}
Run Code Online (Sandbox Code Playgroud)
如果pts向量为空,上面的代码将会出现问题,因为pts.size()-1在这种情况下,这是一个巨大的无意义数字.处理与常用值a < b-1不同的表达式a+1 < b就像在雷区中跳舞一样.
从历史上看,size_t无符号的理由是能够为值使用额外的位,例如,在16位平台上能够在阵列中使用65535个元素而不是32767个元素.在我看来,即使在那个时候,这个错误的语义选择的额外成本也不值得获得(如果32767元素现在还不够,那么65535就不够长了).
无符号值非常有用,但不是用于表示容器大小或索引; 对于大小和索引,常规有符号整数的工作要好得多,因为语义是你所期望的.
当您需要模运算属性或希望在位级工作时,无符号值是理想类型.
Jen*_*edt 31
这是一种更普遍的现象,通常人们不会使用正确的整数类型.Modern C具有语义typedef,它比原始整数类型更优选.例如,所有"大小"都应该输入为size_t.如果系统地将语义类型用于应用程序变量,那么使用这些类型的循环变量也会变得更加容易.
而且我已经看到了一些很难发现的错误来自使用int左右.代码突然崩溃在大矩阵和类似的东西上.只需使用正确的类型正确编码即可避免这种情
这纯粹是懒惰和无知。您应该始终使用正确的索引类型,除非您有进一步的信息限制可能的索引范围,否则size_t就是正确的类型。
当然,如果维度是从文件中的单字节字段读取的,那么您就知道它的范围在 0-255 之间,并且int是一个完全合理的索引类型。同样,int如果您循环固定次数(例如 0 到 99),也可以。但是还有另一个不使用的原因int:如果您i%2在循环体中使用不同的方式处理偶数/奇数索引,i%2则成本要高得多什么时候i签名比什么时候i未签名...