在..中使用short而不是int的好处.环

Benefit of using short instead of int in for... loop

本文关键字:int short      更新时间:2023-10-16

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

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

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

不,没有任何好处。总之,short可能会占用一个完整的寄存器(32位,一个int)。

在IDE中输入额外的两个字母也会浪费几个小时。(那是个笑话)。

否。循环变量可能会被分配给一个寄存器,因此它最终会占用相同的空间。

查看生成的汇编代码,您可能会发现使用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    

通常情况下,当有人没有注意到(或忘记)这是一个狭窄的数据类型时,尝试为此进行优化只会加剧错误。例如,看看我研究过的这个bcrypt问题。。。非常典型:

BCrypt说类似的长密码是等价的——我、宝石还是密码学领域的问题?

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

如果你还没有遇到过的话,我在这里谈论的一些w/numeric_limits可能是有信息的或有趣的:

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

没有。无论如何,您的计数器很可能最终会出现在寄存器中,并且它们通常至少与int 大小相同

我认为没有太大区别。编译器可能会为计数器变量使用整个32位寄存器(在32位模式下)。在最坏的情况下(当不使用寄存器时),您最多只会浪费堆栈中的两个字节

如果循环索引永远不会为负,则作为循环计数器的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 上的本机-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 上的本机-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-在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的情况下,它实际上使用了更少的字节。

正如大多数其他人所说,在计算上没有优势,可能会更糟。然而,如果循环变量用于需要短路的计算,那么它可能是合理的:

for(short j = 0; j < 5; j++)
{
   // void myfunc(short arg1);
   myfunc(j);
}

真正所做的只是防止出现警告消息,因为传递的值将被提升为int(取决于编译器、平台和C++方言)。但它看起来更干净,IMHO。

当然不值得纠缠。如果你想优化,请记住规则(忘记是谁想出的):

  1. 不要
  2. 步骤1,第一个措施失败
  3. 做出改变
  4. 如果无聊,退出,否则转到步骤2