8

is there any benefit to using short instead of int in a for loop? i.e.

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

99% of my loops involve numbers below 3000, so I was thinking ints would be a waste of bytes. Thanks!

Matthias D
  • 1,581
  • 2
  • 13
  • 17

8 Answers8

12

No, there is no benefit. The short will probably end up taking a full register (which is 32 bits, an int) anyway.

You will lose hours typing the extra two letters in the IDE, too. (That was a joke).

John Leehey
  • 22,052
  • 8
  • 61
  • 88
9

No. The loop variable will likely be allocated to a register, so it will end up taking up the same amount of space regardless.

hammar
  • 138,522
  • 17
  • 304
  • 385
6

Look at the generated assembler code and you would probably see that using int generates cleaner code.

c-code:

#include <stdio.h>

int main(void) {
    int j;

    for(j = 0; j < 5; j++) {
        printf("%d", j);
    }
}

using short:

 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    

using 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    
Ólafur Waage
  • 68,817
  • 22
  • 142
  • 198
Fredrik Pihl
  • 44,604
  • 7
  • 83
  • 130
  • Except for the "padding" (?) what is cleaner? –  Jun 07 '11 at 19:18
  • the only difference I can see is that it uses addw (add word?),movl and cmpw instead of addl and cmpl, etc... whats cleaner? – John Leehey Jun 07 '11 at 19:29
  • perhaps not the best example, but if one do something in the loop e.g. sum of the index variable, will generate different code. Try it your self, that's the lesson here, try and see what you get :-) – Fredrik Pihl Jun 07 '11 at 20:15
  • *face palm*. The int version may be longer as in number/lines of instructions, but if you take a look, the code is smaller, albeit by 2 bytes, even though the int version contains a nop. – Nathan Ernst Jun 07 '11 at 20:28
3

More often than not, trying to optimize for this will just exacerbate bugs when someone doesn't notice (or forgets) that it's a narrow data type. For instance, check out this bcrypt problem I looked into...pretty typical:

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

Yet the problem is still there as int is a finite size as well. Better to spend your time making sure your program is correct and not creating hazards or security problems from numeric underflows and overflows.

Some of what I talk about w/numeric_limits here might be informative or interesting, if you haven't encountered that yet:

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

Community
  • 1
  • 1
0

Nope. Chances are your counter will end up in a register anyway, and they are typically at least the same size as int

Nemanja Trifunovic
  • 24,346
  • 3
  • 50
  • 88
0

I think there isn't much difference. Your compiler will probably use an entire 32-bit register for the counter variable (in 32-bit mode). You'll waste just two bytes from the stack, at most, in the worst case (when not used a register)

A.J.
  • 966
  • 1
  • 9
  • 22
0

One potential improvement over int as loop counter is unsigned int (or std::size_t where applicable) if the loop index is never going to be negative. Using short instead of int makes no difference in most compilers, here's the ones I have.

Code:

volatile int n;
int main()
{
    for(short j = 0; j < 50; j++) // replaced with int in test2
        n = j;
}

g++ 4.5.2 -march=native -O3 on x86_64 linux

// 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=native -O3 on x86_64 linux

// 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

Intel 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

Sun C++ 5.8 -xO5 on sparc

// 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

So of the four compilers I have, only one even had any difference in the result, and, it actually used less bytes in case of int.

Cubbi
  • 46,567
  • 13
  • 103
  • 169
0

As most others have said, computationally there is no advantage and might be worse. However, if the loop variable is used in a computation requiring a short, then it might be justified:

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

All this really does is prevent a warning message as the value passed would be promoted to an int (depending on compiler, platform, and C++ dialect). But it looks cleaner, IMHO.

Certainly not worth obsessing over. If you are looking to optimize, remember the rules (forget who came up with these):

  1. Don't
  2. Failing Step 1, first Measure
  3. Make a change
  4. If bored, exit, else go to Step 2.
Harold Bamford
  • 1,589
  • 1
  • 14
  • 26