为...循环使用short而不是int的好处

时间:2011-06-07 18:47:02

标签: c++ loops for-loop

在for循环中使用short而不是int有什么好处吗? 即。

for(short j = 0; j < 5; j++) {

99%的循环涉及3000以下的数字,所以我认为ints会浪费字节。谢谢!

8 个答案:

答案 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问题......非常典型:

BCrypt says long, similar passwords are equivalent - problem with me, the gem, or the field of cryptography?

然而问题仍然存在,因为int也是一个有限的大小。最好花时间确保您的程序正确,不会因数字下溢和溢出而产生危险或安全问题。

如果您还没有遇到过,我在这里谈论的一些{/ {}}可能会提供信息或有趣的内容:

http://hostilefork.com/2009/03/31/modern_cpp_or_modern_art/

答案 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 ++方言)。但它看起来更干净,恕我直言。

当然不值得痴迷。如果您希望优化,请记住规则(忘记提出这些规则的人):

  1. 不要
  2. 第1步失败,第一次测量
  3. 进行更改
  4. 如果无聊,请退出,否则请转到步骤2.