Преимущество использования short вместо int в for... loop

Есть ли какая-то польза от использования short вместо int в цикле for? т.е.

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

99% моих циклов содержат числа ниже 3000, поэтому я думал, что целые числа будут пустой тратой байтов. Спасибо!

8 ответов

Нет, никакой пользы нет. Короткое замыкание, вероятно, в конечном итоге займет полный регистр (32-битный, int) в любом случае.

Вы также потеряете часы, набрав дополнительные две буквы в IDE. (Это была шутка).

Нет. Переменная цикла, скорее всего, будет выделена регистру, поэтому она будет занимать одинаковое количество места независимо.

Посмотрите на сгенерированный ассемблерный код, и вы, вероятно, увидите, что используя int генерирует более чистый код

с-код:

#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 это конечный размер, а также. Лучше потратить время на то, чтобы убедиться, что ваша программа правильная, а не создает опасности или проблемы с безопасностью из-за переполнения и переполнения чисел.

Некоторые из того, что я говорю о ж /numeric_limits здесь может быть информативным или интересным, если вы еще не сталкивались с этим:

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

Как сказали многие другие, в вычислительном отношении нет никаких преимуществ и может быть хуже. Однако, если переменная цикла используется в вычислениях, требующих короткого замыкания, то это может быть оправдано:

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

Все, что на самом деле делает, - это предотвращает появление предупреждающего сообщения, поскольку переданное значение будет преобразовано в int (в зависимости от компилятора, платформы и диалекта C++). Но выглядит чище, ИМХО.

Конечно, не стоит зацикливаться на этом. Если вы хотите оптимизировать, помните правила (забудьте, кто придумал это):

  1. не
  2. Сбой шага 1, первая мера
  3. Изменить
  4. Если вам скучно, выйдите, иначе перейдите к шагу 2.

Нету. Скорее всего, ваш счетчик окажется в регистре в любом случае, и они, как минимум, имеют такой же размер, как 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 = native -O3 в Linux x86_64

// 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 в Linux x86_64

// 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 - быстрый на 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 на спарке

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

Другие вопросы по тегам