现代编译器是否优化了 unsigned int 在 for 循环中的使用?
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
?
与 int
相比,在 for 循环中使用 unsigned int
没有任何优势。使用 unsigned int
的数字范围的边际收益远远超过引入错误的机会。此外,unsigned int
使可读性更难。
一个可能引入错误的有趣案例是
for (unsigned int i = foo.Length()-1; i >= 0; --i) ...
您可能已经注意到,这个循环永远不会结束。一些现代 gcc 编译器可能会在这种情况下提供警告,但有时它们不会。比较 signed
和 unsigned
值时也会出现一些错误。如果您需要额外的 space,最好使用 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
考虑以下代码:
for(unsigned i = 0; i < counter1; i++) {
for(unsigned j = 0; j < counter2; j++) {
// some code here
}
}
在此上下文中使用 unsigned int
而不是仅使用 int
有什么好处吗?现代编译器会以某种方式优化它,还是唯一的好处只是更大的 unsigned int
?
与 int
相比,在 for 循环中使用 unsigned int
没有任何优势。使用 unsigned int
的数字范围的边际收益远远超过引入错误的机会。此外,unsigned int
使可读性更难。
一个可能引入错误的有趣案例是
for (unsigned int i = foo.Length()-1; i >= 0; --i) ...
您可能已经注意到,这个循环永远不会结束。一些现代 gcc 编译器可能会在这种情况下提供警告,但有时它们不会。比较 signed
和 unsigned
值时也会出现一些错误。如果您需要额外的 space,最好使用 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