现代编译器是否优化了for循环中使用的无符号int
Do the modern compilers optimize unsigned int use in for loops?
考虑以下代码:
for(unsigned i = 0; i < counter1; i++) {
for(unsigned j = 0; j < counter2; j++) {
// some code here
}
}
在这种情况下使用unsigned int
而不仅仅是int
有什么好处吗?现代编译器会以某种方式优化它吗?还是唯一的好处只是unsigned int
的更大尺寸?
在for循环中使用unsigned int
与int
相比没有任何优势。使用unsigned int
的数字范围内的边际收益远远超过引入错误的机会。此外,unsigned int
使可读性更加困难。
是一个可能引入错误的有趣案例
for (unsigned int i = foo.Length()-1; i >= 0; --i) ...
正如您可能注意到的,这个循环永远不会结束。一些现代gcc编译器可能会在这种情况下提供警告,但有时不会。在比较signed
和unsigned
的值时也可能出现一些错误。如果你需要额外的空间,最好用long
而不是unsigned int
。
特别是谈到使用unsigned int
的编译器优化,没有任何好处。
这些循环的编译器结果没有区别,因为在汇编中,除了比较之外,大多数情况下对无符号整数的处理并没有什么不同。不过,治疗师提到的虫子在其他情况下也是相关的。
$ cat test.c
#include <stdlib.h>
#include <stdio.h>
int main(void) {
unsigned buffer[100][100];
for (unsigned i = 0; i < 100; i++)
for (unsigned j = 0; j < 100; j++)
fprintf(stdout, "i");
}
$ sed s/unsigned/int/ test.c > testint.c
$ gcc -std=c11 -O3 testint.c -S; gcc -std=c11 -O3 test.c -S
$ diff test.s testint.s
1c1
< .file "test.c"
---
> .file "testint.c"
如果我使用-O0
,你会看到分支时的差异:
$ diff test.s testint.s
1c1
< .file "test.c"
---
> .file "testint.c"
27c27
< jbe .L4
---
> jle .L4
31c31
< jbe .L5
---
> jle .L5
相关文章:
- 如何在C++中将一个无符号的 int 转换为两个无符号的短裤?
- 在 std::无符号字符的向量处存储 int 的十六进制表示形式
- 从 std::vector<无符号字符>切片中提取 int?
- 是什么导致了这种使用三进制而不是短整型的有符号int到无符号int转换
- C++无符号短裤的划分导致 int
- 将无符号转换为复杂<int>原因符号转换警告
- 如何解决隐式转换丢失整数精度:'size_t'(又名"无符号长")到'int'警告?
- 无符号的 int 到有效数字
- C++:使用没有位移位的指针将无符号字符转换为无符号 int
- 整数类型应该显式转换(例如"int"到"无符号")还是只会增加混乱?
- 有没有办法在C++中将mpz_t转换为 int 或无符号长 int?
- 是否可以将无符号 int 的最大值转换为 int 并将结果转换为 -1?
- 为什么QByteArray的大小是"int"而不是"无符号int"
- 为什么 (-i) 的类型(其中 i 是无符号的 int)仍然是无符号的 int?
- 无符号长整型和无符号 int 之间有什么区别,这 2 种类型应该如何在 c# 中封送?
- 如何对无符号长 int 进行位掩码?
- 使用无符号int作为二进制来在c++中实现一个集
- 这个右移是如何工作的:字符串流>>无符号的int>>无符号的int?
- 转换 int -> 无符号长 长 是否由标准定义
- 为什么在执行 int / 无符号 int 除法时使用 'divl'