在for循环中使用short而不是int有什么好处吗? 即。
for(short j = 0; j < 5; j++) {
99%的循环涉及3000以下的数字,所以我认为ints会浪费字节。谢谢!
答案 0 :(得分:8)
没有。循环变量可能会被分配给一个寄存器,因此它最终会占用相同的空间量。
答案 1 :(得分:8)
不,没有任何好处。无论如何,short可能会最终获得一个完整的寄存器(32位,一个int)。
您也将失去在IDE中输入额外两个字母的时间。 (那是一个笑话)。
答案 2 :(得分:6)
查看生成的汇编程序代码,您可能会看到使用int
生成更清晰的代码。
C代码:
#include <stdio.h>
int main(void) {
int j;
for(j = 0; j < 5; j++) {
printf("%d", j);
}
}
使用短语:
080483c4 <main>:
80483c4: 55 push %ebp
80483c5: 89 e5 mov %esp,%ebp
80483c7: 83 e4 f0 and $0xfffffff0,%esp
80483ca: 83 ec 20 sub $0x20,%esp
80483cd: 66 c7 44 24 1e 00 00 movw $0x0,0x1e(%esp)
80483d4: eb 1c jmp 80483f2 <main+0x2e>
80483d6: 0f bf 54 24 1e movswl 0x1e(%esp),%edx
80483db: b8 c0 84 04 08 mov $0x80484c0,%eax
80483e0: 89 54 24 04 mov %edx,0x4(%esp)
80483e4: 89 04 24 mov %eax,(%esp)
80483e7: e8 08 ff ff ff call 80482f4 <printf@plt>
80483ec: 66 83 44 24 1e 01 addw $0x1,0x1e(%esp)
80483f2: 66 83 7c 24 1e 04 cmpw $0x4,0x1e(%esp)
80483f8: 7e dc jle 80483d6 <main+0x12>
80483fa: c9 leave
80483fb: c3 ret
使用int:
080483c4 <main>:
80483c4: 55 push %ebp
80483c5: 89 e5 mov %esp,%ebp
80483c7: 83 e4 f0 and $0xfffffff0,%esp
80483ca: 83 ec 20 sub $0x20,%esp
80483cd: c7 44 24 1c 00 00 00 movl $0x0,0x1c(%esp)
80483d4: 00
80483d5: eb 1a jmp 80483f1 <main+0x2d>
80483d7: b8 c0 84 04 08 mov $0x80484c0,%eax
80483dc: 8b 54 24 1c mov 0x1c(%esp),%edx
80483e0: 89 54 24 04 mov %edx,0x4(%esp)
80483e4: 89 04 24 mov %eax,(%esp)
80483e7: e8 08 ff ff ff call 80482f4 <printf@plt>
80483ec: 83 44 24 1c 01 addl $0x1,0x1c(%esp)
80483f1: 83 7c 24 1c 04 cmpl $0x4,0x1c(%esp)
80483f6: 7e df jle 80483d7 <main+0x13>
80483f8: c9 leave
80483f9: c3 ret
答案 3 :(得分:3)
当有人不注意(或忘记)它是一种狭窄的数据类型时,尝试对此进行优化只会加剧错误。例如,看看我调查的这个bcrypt问题......非常典型:
然而问题仍然存在,因为int
也是一个有限的大小。最好花时间确保您的程序正确,不会因数字下溢和溢出而产生危险或安全问题。
如果您还没有遇到过,我在这里谈论的一些{/ {}}可能会提供信息或有趣的内容:
答案 4 :(得分:0)
不。无论如何,你的计数器最终会进入一个寄存器,它们通常至少与int相同
答案 5 :(得分:0)
我认为差别不大。您的编译器可能会使用整个32位寄存器作为计数器变量(在32位模式下)。在最坏的情况下(当没有使用寄存器时),你最多只会浪费堆栈中的两个字节
答案 6 :(得分:0)
如果循环索引永远不会为负,那么循环计数器的int
的一个潜在改进是unsigned int
(或适用的std::size_t
)。使用short
代替int
在大多数编译器中没有任何区别,这就是我的编译器。
代码:
volatile int n;
int main()
{
for(short j = 0; j < 50; j++) // replaced with int in test2
n = j;
}
g ++ 4.5.2 -march = x86_64 linux上的native -O3
// using short j // using int j
.L2: .L2:
movl %eax, n(%rip) movl %eax, n(%rip)
incl %eax incl %eax
cmpl $50, %eax cmpl $50, %eax
jne .L2 jne .L2
clang ++ 2.9 -march = x86_64 linux上的native -O3
// using short j // using int j
.LBB0_1: .LBB0_1:
movl %eax, n(%rip) movl %eax, n(%rip)
incl %eax incl %eax
cmpl $50, %eax cmpl $50, %eax
jne .LBB0_1 jne .LBB0_1
英特尔C ++ 11.1 -fast on x86_64 linux
// using short j // using int j
..B1.2: ..B1.2:
movl %eax, n(%rip) movl %eax, n(%rip)
incl %edx incl %eax
movswq %dx, %rax cmpl $50, %eax
cmpl $50, %eax jl ..B1.2
jl ..B1.2
sparc上的Sun C ++ 5.8 -xO5
// using short j // using int j
.L900000105: .L900000105:
st %o4,[%o5+%lo(n)] st %o4,[%o5+%lo(n)]
add %o4,1,%o4 add %o4,1,%o4
cmp %o4,49 cmp %o4,49
ble,pt %icc,.L900000105 ble,pt %icc,.L900000105
因此,在我使用的四个编译器中,只有一个编译器在结果上有任何差异,并且在int的情况下它实际上使用了 less 字节。
答案 7 :(得分:0)
正如大多数人所说,计算上没有优势,可能更糟。但是,如果循环变量用于需要短路的计算中,则可能是合理的:
for(short j = 0; j < 5; j++)
{
// void myfunc(short arg1);
myfunc(j);
}
所有这些真的的作用是阻止警告消息,因为传递的值将被提升为int(取决于编译器,平台和C ++方言)。但它看起来更干净,恕我直言。
当然不值得痴迷。如果您希望优化,请记住规则(忘记提出这些规则的人):