Почему в большинстве примеров которые я смотрю в интернете для хранения в переменной целочисленного типа, в которой нужно хранить совсем небольшое значение например 10 или 50 используют int вместо short int, даже если просчеты точно не превысят short int все равно используют int, ведь это же логичнее зачем использовать 4 байта памяти когда можно использовать 2 байта, или людям просто лень писать short перед int. Есть ли в этом какая то разница?
6 Answers
int - это тип по-умолчанию.
Это будет самый оптимальный тип на целевой платформе - 2 байта на 16-разрядной, 4 байта на 32-разрядной, 4 или 8 байт на 64-рязрядной (в зависимости от ОС).
short int требует генерации дополнительного кода на большинстве платформ - например преобразования в int если соответствующая инструкция процессора не работает с short int.
short int может сэкономить место в массиве, но скорей всего не сэкономит место если это поле структуры, локальная переменная или аргумент функции - они будут выравниваться по размеру int или больше.
- 31,143
-
-
-
В реальном коде может быть всё, что угодно. Поэтому последнее утверждение в Вашем ответе, на мой взгляд, не совсем верное. Слишком много оговорок нужно сделать, чтобы оно стало верным. – ixSci Nov 16 '17 at 13:58
-
@Abyx,
"short int требует генерации дополнительного кода на большинстве платформ"-- пруф (особенно про большинство) можно? Во всех ISA (Instruction set architecture) с которыми я сейчас имею дело (включая MIPS) есть инструкции для доступа к half words (если считать word 32-bit) – avp Nov 16 '17 at 19:25 -
@Abyx, gcc на x86 (и amd64) для 2-х short использует
movw(да, если один из операндов int, то move c расширением знака). И в остальных я лишнего кода не вижу. Доступ к памяти всюду 1 команда. Кстати, я тоже посмотрел просто две short переменные и опцию -Os. Каждая 2 байта в стеке. – avp Nov 16 '17 at 21:53 -
@Abyx, если компилятор умный (clang), то будет использовать подходящие регистры и инструкции. То, что gcc генерирует не оптимальный код это вина gcc. С другой стороны, gcc генерирует код, который должен генерировать согласно стандарту. – ixSci Nov 17 '17 at 05:38
Как одна из причин - работа с int'ом обычно выполняется быстрее.
Ну, а экономия в 2 байта при нынешних объемах памяти для обычных задач несущественна.
Если же нужна какая-то специфика - ну, например, строго указанный размер для обмена информацией с другой программой/машиной, больший диапазон значений - словом, некоторые условия, где другой тип применять удобнее (вплоть до экономии памяти в программе, для которой это действительно важно) - тогда дело другое.
- 221,325
Людям лень, это тоже причина. Но есть и другие, как например то, что в любом выражении short будет всё равно преобразован к int (integral promotion), т.е. имея переменную типа int мы, потенциально, имеем меньший шанс того, что будет необходимо преобразование типа во время вычисления выражения.
Но я рискну предположить, что многие пишущие на C++ не догадываются об этой разнице и о том, какие там инструкции и что быстрее. Поэтому, на мой взгляд, основной причиной использования int является привычка и лень, больше ничего. И дело тут не только в short. К примеру, очень часто size_t является более подходящим (с точки зрения семантики) типом, а люди всё равно используют int.
- 23,825
-
@Abyx, я всё-таки в духе языка отвечал, оптимизатор может вообще целые куски кода выкидывать и преобразовывать их в математические формулы. – ixSci Nov 16 '17 at 14:02
-
Пытаться использовать short вместо int это преждевременная и/или неэффективная оптимизация как правило.
При выполнении арифметических операций малые типы (< rank) в int превращаются (или unsigned если в int не помещается значение) из-за integral promotions.
Объяснить зачем integral promotions в языке существуют можно так: int обычно имеет естественную ширину для процессора, поэтому меньше действий CPU обычно нужно сделать, чтобы сложить два int, по сравнению c short int. К примеру, код:
using U = unsigned short;
U add(U a, U b) {
return a + b;
}
может скомпилироваться в:
leal (%rsi,%rdi), %eax
то есть происходит фактически происходит операция над машинными словами (в AMD64 регистрах). Это происходит, даже если 8-битовые числа складывать.
CPU c памятью по словам работает (к примеру, 64-битные слова). Поэтому, доступ может быть быстрее, если данные расположены по адресу кратному размеру слова (data alignment). Компилятор может добавить дополнительные байты (ничего не значащие), чтобы выравнять данные по границе слова (padding) или упаковать несколько меньших элементов в одном слове (packing). Выравнивание данных.
- 52,361
-
@Abyx: наличие оптимизации не влияет на факт, что машинные слова используются, попробуйте скомпилировать c -O0. Сравните с
unsigned int(тоже c -O0). Я привёл вариант с -Os для краткости – jfs Nov 16 '17 at 14:14 -
@Abyx: и как часто вы на практике short по ссылке передаёте? И какое это отношение к моему примеру имеет, про который вы написали "попробуйте скомпилировать с -O0". Почитайте лучше в стандарте о integral promotions, чтобы людей в заблуждение не вводить. – jfs Nov 16 '17 at 14:33
-
@Abyx 1- integral promotions существуют. Это понятие из c++ стандарта. 2- c++ код в ответе показывает пример когда эти преобразования могут быть 3- Показан пример asm, который компилятор может сгенерировать 4- Слово "кодогенерация" не используется в ответе. Ответ предполагает, что компилятор не нарушает стандарт. О том как конкретно генерация происходит, ни слова не сказано, не нужно придумывать. С каким пунктом или предложением в ответе вы не согласны? Явно цитируйте, не нужно мне приписывать ничего. – jfs Nov 16 '17 at 15:49
-
-
@Abyx: вы бы хотя бы на ссылку "usual arithmetic conversions" нажали и почитали: " then before any other action (...), the operand undergoes integral promotion." – jfs Nov 16 '17 at 16:42
-
@Abyx ссылка из вашей цитаты, которую вы сами привели. Ссылка в ответе к этому не относится (её можно поправить добавив # часть, чтобы сразу на заголовок приземлится (но это не имеет отношения к цитате из комментария)). – jfs Nov 16 '17 at 16:57
-
@Abyx 1- вы пытаетесь сказать, что для int нужно больше действий на CPU чем для short (пример, что это не так, по ссылкам с -O0 наверху). Вы сами себе противоречите. Ваш ответ же говорит: "short int требует генерации дополнительного кода на большинстве платформ" 2- Про размеры int согласен. Могло создаться впечатление, что размер должен быть 64. Это не так. Сам asm приведён как пример, что компилятор больший размер может использовать. Проиллюстрировать, что использование short не оптимизирует здесь — код с U int вероятно идентичный результат даёт — подтверждает первый тезис в ответе. – jfs Nov 16 '17 at 17:21
-
@Abyx 1- вы привели мою цитату про меньше действий. Если вы с ней согласны, то к чему приводить. 2- В свою очередь: не нужно мне приписывать выводы. Я уже это говорил. Ещё раз: нет слова "кодогенерация" в моём ответе. Используйте прямые цитаты используйте, с которыми не согласны. Не нужно фантазировать. – jfs Nov 16 '17 at 17:34
-
@Abyx я о том что вы уже не однократно пытаетесь приписать мне утверждения. Слово "кодогенерация" я употребил, чтобы вы свою цитату могли найти: "Вы неправильно указываете причину кодогенерации" . Приведите цитату с причиной (вы не сможете, я не обсуждал "причины кодогенерации"). – jfs Nov 16 '17 at 18:00
-
@Abyx вы разницу понимаете между "A does B" и "A does B because X,Y,Z". Я сказал первое (что 100% истинно — ссылка подтверждает). Вы придумали второе (о причинах начали говорить). – jfs Nov 16 '17 at 18:26
Скорее всего, большая часть просмотренных примеров фокусируются на чем-то еще, а не использовании наиболее подходящего типа данных. Соответственно используют int просто потому, что это встроенный целочисленный тип по-умолчанию (да еще и самым коротким именем). В реальных проектах целочисленный тип во-первых подбирают исходя из диапазона хранимых значений, во-вторых вместо int short unsigned int long и т.п. используют библиотечные целочисленные типы фиксированной длины, например ::std::int16_t или ::std::int32_t, из заголовочного файла <cstdint> и целочисленные типы для памяти, например ::std::size_t или ::std::ptr_diff_t, из заголовочного файла <cstddef>.
- 29,796
Разнообразие используемых типов приводит к необходимости их преобразования, из чего вытекают всякие сложности и тонкие моменты. Поэтому, когда в разнообразии типов нет обоснованной необходимости, то стараются это разнообразие сократить.
Собственно, бритва Оккама в чистом виде: "Не следует множить сущее без необходимости".
А int лучше всего подходит для основной массы целочисленных вычислений (в этом, собственно, его назначение, он оптимален для этого на данной машине). Поэтому обычно его и берут, если нет каких-то веских причин взять другой тип.
Причинами для выбора другого типа могут быть:
- Недостаточно широкий диапазон значений int;
- Необходимость экономии памяти на больших массивах данных;
- особенности конкретного прикладного протокола
и так далее.
- 1,983
-
-
Ваш ответ сложен для восприятия, отсюда и минусы. Вот даже я первый раз прочитал его неправильно... – Pavel Mayorov Nov 16 '17 at 13:39
-
@Pavel Mayorov, минусовать имеет смысл, когда ответ "не является полезным", то есть отвечает на вопрос неверно, или вообще не отвечает. Если же он вам просто не нравится (в силу трудности восприятия или еще чего) - просто не плюсуйте. А то по вашей логике я должен минусовать все, что не понял. Так что-ли? – Voidificator Nov 16 '17 at 13:53
-
2Сложный для восприятия ответ который тяжело прочесть правильно определенно полезным не является. – Pavel Mayorov Nov 16 '17 at 13:54
-
3Да, вы можете минусовать все что не поняли, у вас есть такое право. – Pavel Mayorov Nov 16 '17 at 13:54
-
@Pavel Mayorov, технически я могу минусовать вообще все, что угодно. Речь идет не о праве, а о разумном правиле его применения. На мой взгляд, ваше правило не способствует развитию подобных сообществ. – Voidificator Nov 16 '17 at 14:16
-
"когда в разнообразии типов нет обоснованной необходимости, то стараются это разнообразие сократить" - полностью поддерживаю. Мешанина из разнотипных локальных целочисленных переменных, лично меня, немного напрягает. – wololo Nov 17 '17 at 09:50
int'ом обычно быстрее. Экономия в 2 байта при нынешних объемах памяти для обычных задач несущественна... – Harry Nov 16 '17 at 12:46sizeof(char)равен 1. Об этом написано как в сишном, так и в плюсовом стандартах. – αλεχολυτ Nov 17 '17 at 21:31sizeof(char), бесспорно, 1. Ноsizeof(...)— это не размер в байтах, это размер вchar'ах! Аcharможет быть, насколько я понимаю, и не 8-битным. В то время как байт всегда 8-битный. – VladD Nov 17 '17 at 21:39char. И количество в нем бит не обязано быть везде и всегда 8. – αλεχολυτ Nov 17 '17 at 21:56