Когда использовать разные целочисленные типы? - PullRequest
11 голосов
/ 11 июня 2011

Языки программирования (например, c, c ++ и java) обычно имеют несколько типов для целочисленной арифметики:

  • signed и unsigned типы
  • типы разного размера: short, int, long, long long
  • типы гарантированных и негарантированных (т.е. зависящих от реализации) размеров:
    например int32_t против int (и я знаю, что int32_t не является частью языка)

Как бы вы подвели итог, когда следует использовать каждый из них?

Ответы [ 8 ]

9 голосов
/ 11 июня 2011

Интегральный тип по умолчанию (int) получает привилегированный режим «первый среди равных» почти во всех языках. Таким образом, мы можем использовать это как значение по умолчанию, если нет причин предпочитать другой тип.

Такими причинами могут быть:

  • Использование большего типа, если вы знаете, что вам нужен дополнительный диапазон, или меньшего типа, если вы хотите сохранить память и не обращать внимания на меньший диапазон.
  • Использование типа без знака, чтобы убедиться, что вы не получите никаких «лишних» 1 в вашем целочисленном представлении, если намереваетесь использовать операторы смещения битов (<< и >>).
  • Если язык не гарантирует минимальный (или даже фиксированный) размер для типа (например, C / C ++ против C # / Java), и вы заботитесь о его свойствах, вам следует предпочесть некоторый механизм генерации типа с гарантированным размером (например, int32_t) - если ваша программа должна быть переносимой и предполагается, что она будет скомпилирована с другими компиляторами, это становится более важным.

Обновление (расширение на типы гарантированного размера)

Мое личное мнение таково, что типы без гарантированного фиксированного размера - это больше проблем, чем стоит сегодня. Я не буду вдаваться в исторические причины, которые их породили (кратко: переносимость исходного кода), но реальность такова, что в 2011 году очень немногие люди, если таковые имеются, смогут извлечь из них выгоду.

С другой стороны, есть много вещей, которые могут пойти не так при использовании таких типов:

  • Тип не имеет необходимого диапазона
  • Вы обращаетесь к основной памяти для переменной (возможно, для ее сериализации), но из-за порядкового номера процессора и нефиксированного размера типа вы в конечном итоге вносите ошибку

По этим причинам (и, возможно, есть и другие) использование таких типов в теории является основной болью. Кроме того, если extreme мобильность не является требованием, вы не получите никакой выгоды, чтобы компенсировать. И действительно, вся цель typedefs, например int32_t, состоит в том, чтобы полностью исключить использование типов со свободным размером.

На практике, если вы знаете, что ваша программа не будет портирована на другой компилятор или архитектуру, вы можете игнорировать тот факт, что типы не имеют фиксированного размера, и обрабатывать их так, как если бы они были известным размером вашего компилятора использует для них.

6 голосов
/ 11 июня 2011

По одному на ваши вопросы:

  1. signed и unsigned: зависит от того, что вам нужно. Если вы уверены, что номер будет без знака - используйте unsigned. Это даст вам возможность использовать большие числа. Например, signed char (1B) имеет диапазон [- 128: 127] , но если оно unsigned - максимальное значение удваивается (вам нужно использовать еще один бит - знаковый бит , поэтому unsigned char может быть 255 (все биты равны 1)

  2. short, int, long, long long - это довольно ясно, не так ли? Наименьшее целое число (кроме char) равно short, следующее - int и т. Д. Но они зависят от платформы - int может быть 2B (очень давно: D), 4B (обычно). long может быть 4B (на 32-битной платформе) или 8B (на 64-битной платформе) и т. Д. long long не является стандартным типом в C ++ (это будет в C ++ 0x), но обычно это typedef для int64_t.

  3. int32_t против int - int32_t и другие подобные типы гарантируют их размер. Например, int32_t гарантированно будет 32-битным, в то время как, как я уже сказал, размер int зависит от платформы.

4 голосов
/ 11 июня 2011

используйте короче, чтобы сохранить память, дольше, чтобы иметь возможность представлять большие числа.Если у вас нет таких требований, подумайте, с какими API вы будете обмениваться данными, и настройте себя так, чтобы вам не приходилось слишком много приводить или преобразовывать.

2 голосов
/ 11 июня 2011

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

Сказав это, как указывает Крис, люди используют шорты против целых для сохраненияобъем памяти.Подумайте о следующем сценарии: у вас есть 1 000 000 (довольно небольшое число) целых (обычно 32 байта) по сравнению с короткими (обычно 16 байтов).Если вы знаете, что вам никогда не понадобится представлять число больше 32 767, вы можете использовать короткий.Или вы можете использовать шрифт без знака, если вы знаете, что вам никогда не понадобится представлять число больше 65 535.Это сэкономит: ((32 - 16) x 1 000 000) = 16 КБ памяти.

1 голос
/ 15 июля 2013

Может быть, просто для удовольствия, здесь у вас есть простой пример, показывающий, как в зависимости от того, какой тип вы выбираете, у вас есть один результат или другой.

Естественно, фактическая причина, по которой вы бы выбрали тот или иной тип, на мой взгляд, связана с другими факторами.Например, великий оператор сдвига .

#include <iostream>
#include <cmath>
using namespace std;

int main()
{
    int i;

    //unsigned long long x;
    //int x;
    short x;

    x = 2;
    for (i=2; i<15; ++i)
    {
        x=pow(x,2);
        cout << x << endl;
    }
    return 0;
}
1 голос
/ 11 июня 2011

Как правило, вы используете int, если вам не нужно расширять его, потому что вам нужен больший диапазон или вы хотите уменьшить его, потому что вы знаете, что значение имеет смысл только в меньшем диапазоне. Это невероятно редко, что вам нужно изменить из-за соображений памяти - разница между ними незначительна.

1 голос
/ 11 июня 2011

Потребность в целочисленных типах разного размера возникает из-за двух основных проблем: размер шрифта в значительной степени необходимо знать на низком уровне, а в старые времена ограничений памяти это было важно при повседневном использовании, так как у вас было мало играть с. Если вы занимаетесь базовой арифметикой, то практически неважно, какой тип вы используете. Например, при цикле от 1 до 100 не очень важно, используете ли вы uint16_t или uint64_t, при условии, что ваши типы соответствуют, и вы используете правильный тип, если вам нужна / не нужна подпись.

Однако, это становится важным, когда вы хотите масштабировать / нужно оптимизировать. Если вы хотите выделить 1 000 000 000 таких целых чисел, то сказать: «каждое из них будет 64-разрядным на всякий случай» или «я буду использовать встроенный тип» не собирается его сокращать - это 8 000 000 000 байт, что составляет около 7,5 ГБ. данных. Сейчас 1 миллиард 64-битных целых чисел не представляется возможным, но это могут быть точки в трехмерном массиве (1000 ^ 3), и в этом случае у вас также есть размеры указателя на содержимое. Например, вы можете пойти гораздо дальше с 8-битными целыми числами для ваших значений. Сколько вы можете выделить, затем информирует ваши алгоритмы - если вы не можете выделить такое количество данных одновременно, вы можете рассмотреть mmap или обработку части данных одновременно (например, обработка обмена самостоятельно). Если вам не нужны значения определенного размера, тогда вы начнете использовать более ограниченные типы. Точно так же вы получаете дополнительную мощность 2, используя неподписанные типы. Очень полезно.

Если вы когда-либо пишете ассемблер для своего C / C ++, то знание размера типа данных очень важно, особенно когда речь идет о выделении локального стекового пространства или чтении переменных из адресов памяти (в отличие от чтобы уже в реестре). Думайте об этом как о программировании, полностью использующем void*. Поэтому я склонен использовать stdint.h определенных типов по привычке, так что я всегда знаю о своих размерах и форматах при их смешении.

1 голос
/ 11 июня 2011

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

Библиотеки, такие как GMP и OpenSSL, предоставляют "большие числа", которые поддерживают произвольно большие результаты -это обычно самая безопасная вещь, если вы не можете доказать, что результаты ваших вычислений находятся в пределах допустимых границ.

Кроме того, многие языки по умолчанию имеют неограниченные целочисленные типы, поскольку они безопаснее.

...