Ответ 1
Хорошая вещь о базовом типе "int" заключается в том, что он почти всегда будет самым быстрым целым типом для любой платформы, на которой вы сейчас компилируете.
С другой стороны, преимущество использования, скажем, int32_t (а не только int) заключается в том, что ваш код может рассчитывать на то, что int32_t всегда имеет ширину в 32 бита независимо от того, на какой платформе он скомпилирован, что означает, что вы можете безопасно сделайте больше предположений о поведении значения, чем вы могли бы с помощью int. При использовании типов фиксированного размера, если ваш код вообще компилируется на новой платформе Y, тогда он будет более точно вести себя так же, как на старой платформе X.
Недопустимым (теоретическим) недостатком int32_t является то, что новая платформа X может не поддерживать 32-битные целые числа (в этом случае ваш код вообще не будет компилироваться на этой платформе), или он может поддерживать их, но обрабатывать их медленнее, чем это будет обрабатывать простые старые функции.
Приведенные выше примеры немного надуманны, так как почти все современные аппаратные средства обрабатывают 32-битные целые числа на полной скорости, но там (и существуют) существуют платформы, где манипуляция с int64_ts медленнее, чем манипуляция с int, поскольку (a) процессор имеет 32-разрядные регистры и поэтому должны разделить каждую операцию на несколько этапов и, конечно, (b) 64-разрядное целое число будет занимать вдвое больше памяти, чем 32-разрядное целое число, что может оказать дополнительное давление на кеши.
Но: имейте в виду, что для 99% пользователей программного обеспечения эта проблема не будет иметь никакого заметного влияния на производительность, просто потому, что 99% программного обеспечения там не связаны с ЦП в эти дни, и даже для кода, который маловероятен, что целочисленная ширина будет большой проблемой производительности. Итак, что это действительно означает, как вы хотите, чтобы ваша целочисленная математика вела себя?
-
Если вы хотите, чтобы компилятор гарантировал, что ваши целые значения всегда занимают 32 бита ОЗУ и всегда будут "обтекать" в 2 ^ 31 (или 2 ^ 32 для беззнакового), независимо от того, на какой платформе вы 'компилируем, переходите к int32_t (и т.д.).
-
Если вы не заботитесь об обертывании (потому что вы знаете, что ваши целые числа никогда не будут завернуты, из-за характера данных, которые они хранят), и вы хотите сделать код немного более переносимым для нечетных/необычных целей компиляции и, по крайней мере, теоретически быстрее (хотя, вероятно, не в реальной жизни), тогда вы можете придерживаться простого старого short/int/long.
Лично я использую типы фиксированного размера (int32_t и т.д.) по умолчанию, если только не существует очень ясной причины, потому что я хочу минимизировать количество вариантов поведения на разных платформах. Например, этот код:
for (uint32_t i=0; i<4000000000; i++) foo();
... всегда будет вызывать foo() ровно 4000000000 раз, тогда как этот код:
for (unsigned int i=0; i<4000000000; i++) foo();
может вызывать foo() 4000000000 раз, или он может перейти в бесконечный цикл, в зависимости от того, является ли (sizeof (int) >= 4) или нет. Конечно, можно было бы вручную проверить, что второй фрагмент не делает этого на какой-либо конкретной платформе, но, тем не менее, с учетом разницы в производительности, равной нулю между двумя стилями, я предпочитаю первый подход, поскольку предсказание его поведения - легкая задача. Я думаю, что подход char/short/int/long был полезен еще в начале C, когда компьютерная архитектура была более разнообразной, а процессоры были достаточно медленными, чтобы достижение полной собственной производительности было более важным, чем безопасное кодирование.