Должен ли я использовать cstdint? - PullRequest
40 голосов
/ 27 мая 2011

Я размышлял над тем, стоит ли мне использовать typedefs внутри <cstdint> или нет.

Я лично предпочитаю писать uint32_t над unsigned int и int8_t над char и т. Д... поскольку это для меня намного более интуитивно понятно.

Что вы, ребята, думаете?Это хорошая идея использовать typedefs из <cstdint> или нет?Есть ли недостатки?

Ответы [ 6 ]

35 голосов
/ 27 мая 2011

На самом деле, я бы предложил использовать оба.

Если вы хотите что-то, что определенно 32-битное без знака, используйте uint32_t.Например, если вы реализуете "struct" для представления внешнего объекта, спецификация которого определяет одно из его полей как 32-разрядное без знака.

Если вы хотите что-то, что является "естественным размером слова машины",используйте int или unsigned int.Например:

for (int i = 0 ; i < 200 ; ++i)
    // stuff

«Естественный размер слова машины» даст вам наилучшую производительность как на современных процессорах, так и на завтрашних.

Используйте «char», если выозначает «характер»;«char» или «unsigned char», если вы имеете в виду «байт».C / C ++ позволяет вам получить доступ к байту произвольного объекта через "char *", строго говоря, не через что-либо другое.

Используйте uint8_t или int8_t, если вам конкретно нужно 8-битное целое число, аналогично uint32_t.

22 голосов
/ 27 мая 2011

Вы должны использовать оба.Вы должны использовать int, как объяснено в других ответах, когда вам нужно целое число «разумного размера».Используйте char, когда вам нужен символ: он самодокументируется.

Вы должны использовать uint32_t и друзей при взаимодействии с внешним миром в двоичном: при сетевом программировании, обработке бинарных файлов или использовании чужих-байтовые кодировки и т. д. В этих случаях точный размер типа имеет решающее значение для написания правильного, переносимого, самодокументируемого кода.Вот для чего <stdint.h> (или C ++ 0x <cstdint>).

(Порядковый порядок одинаково важен, но это совсем другое дело.)

4 голосов
/ 27 мая 2011

Это зависит от назначения переменной.

Если вам нужен счетчик цикла, используйте int.Если вам нужна строка, используйте массив char.

Если вам нужна числовая переменная, которая может содержать от -1 до 100, int8_t хорошоЕсли вам нужно представить значение от 0 до 100 000, то uint32_t uint_least32_t (спасибо @Serge) - отличный выбор.

3 голосов
/ 27 мая 2011

Одна конкретная ситуация, в которой вам понадобится для использования typedefs из cstdint, - это когда вы работаете с кодом, который выполняет много преобразований указателя в int, и в этом случае использование intptr_t является абсолютным требованием..

В компании, в которой я работаю, мы готовимся к переходу с 32-битного на 64-битный тонны некачественного кода C / C ++, который продолжает приводить указатели к int, а затем обратно к указателям, которые определенно потерпят неудачу на.64-битные архитектуры, поэтому мы попытаемся дезинфицировать код всякий раз, когда это возможно (т. Е. Изменять структуры данных и интерфейсы, чтобы полностью исключить необходимость в приведениях), и везде использовать intptr_t вместо int.

С другой стороны: приведениев общем, это должно вызывать подозрения, но если серьезно, приведение указателей к целым числам почти всегда является следствием серьезного недостатка где-то в вашем дизайне.По сути, вы врете компилятору, платформе и, что более важно, вашим коллегам каждый раз, когда вы прячете указатель за int.

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

1 голос
/ 27 мая 2011

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

Просто используйте typedef.

Независимо от того, нужен ли вам unsigned int или uint32_t (о чем вы можете подумать позже, когда у вас будет более полное представление о том, какой будет ваша программа), использование typedef поможет вам сделать код более понятным, указав вы действительно манипулируете, и вам будет легче перейти на другой тип, когда вы определите месяцы спустя, что ваш первоначальный выбор был худшим. Здесь нет «правильного ответа», потому что вы обычно разбираетесь в этих вещах трудным путем. Взаимодействие между некоторой библиотекой, которая хочет uint32_t, и некоторой другой библиотекой, которая хочет int, является болезненным.

0 голосов
/ 23 января 2012

Используйте template s и общее программирование, где это возможно.Не полагайтесь на любой тип, если вам не нужно!

Если у вас есть функция, которая берет число и возвращает его, умноженное на 2, напишите его так:

template <typename Number>
inline Number doubleNum(Number n) {
  return 2*n;
}

Или даже так:

template <typename RetType, typename NumberType>
inline RetType doubleNum(NumberType n) {
  return 2*n;
}

Таким образом, если у вас есть библиотека, которая использует int s, double s, uint64_t s - вы называете это - выможет работать с ним, не переписывая свой код.Если вам нужно работать с двоичными файлами или сетевым программированием, вы можете работать с типами фиксированного размера, не переписывая код.А если вам нужны числа произвольной точности, вы можете работать с классом, который реализует тот же интерфейс, что и примитивный целочисленный тип или тип с плавающей запятой, посредством перегрузки операторов, такой как обертка GMP, без переписывания кода .

И вы можете специализировать шаблонные функции или классы, чтобы оптимизировать конкретные случаи или работать с классами (или C struct s), которые не соответствуют соответствующему интерфейсу:

/*
 * optimization:
 * primitive integers can be bit-shifted left to
 * achieve multiplication by powers of 2
 * (note that any decent compiler will do this
 *  for you, behind the hood.)
 */
template <>
inline int doubleNum<int>(int n) {
  return n<<1;
}
/*
 * optimization:
 * use assembly code
 */
template <>
inline int32_t doubleNum<int32_t>(int32_t n) {
  asm {
    ...
  }
}
/*
 * work with awkward number class
 */
template <>
inline AwkwardNumber doubleNum<AwkwardNumber>(AwkwardNumber n) {
  n.multiplyBy(2);
  return n;
}
...