char как числовой тип низкого диапазона?


При программировании на языке Си иногда мои функции получают числовые значения, которые всегда будут находиться в диапазоне от 0 до 4. 32-разрядный int может содержать до 2,147,483,647. Это много выделенной памяти, которую я не использую. Самый низкий тип диапазона, который я знаю, это char (который имеет место от 0 до 255, верно?). Это хорошая практика, чтобы использовать его для хранения низких числовых значений диапазона? Есть ли какой-нибудь другой тип, который я могу использовать?

7 3

7 ответов:

Если это аргумент скалярной функции, то он, безусловно, будет повышен до по крайней мере 32-битного типа на практике при передаче функции, поэтому использование char не будет иметь практического значения. Я думаю, что лучше пойти на читаемость, и int является очевидным типом "общее целочисленное значение".

Однако, если у вас потенциально есть большой массив значений, использование char позволит более плотно упаковывать значения в памяти. Если вы действительно нажаты на память, вы можете упаковать их даже плотнее, используя всего 3 или 4 бита на значение (3-это минимум, 4 выравнивается более красиво). Однако это, безусловно, будет менее эффективно обрабатывать.

Если вам действительно нужно сэкономить место, вы можете использовать битовые поля. Обратите внимание, однако, что вам, вероятно, потребуется больше циклов для доступа к данным. (Даже доступ к символу на современном оборудовании может занять больше циклов, чем собственные целочисленные размеры)

(изменить, чтобы привести пример:

struct packed_values
{
     unsigned int val1       : 3; /* ranges from 0-7 */
     unsigned int val2       : 3;
     unsigned int val3       : 3; 
     unsigned int val4       : 3;
     unsigned int val5       : 3;
     unsigned int val6       : 3;
     unsigned int val7       : 3;
     unsigned int val8       : 3;
     unsigned int val9       : 3;
     unsigned int val10      : 3;
     unsigned int padding    : 2; // make this be 32bits
};

packed_value myval;
myval.val1 = 5;
myval.val2 = 6;
myval.val3 = 7;

)

Не используйте char для этой "эффективности" - это просто сбивает с толку/раздражает людей (таких как я :-). Используйте int для общих числовых чисел.

Для точного управления, например для массива 8-битных пикселей RGB, используйте uint8_t.

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

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

Char отлично подходит для удержания низких значений диапазона. Это обеспечивает эффективность, особенно когда у вас есть большое количество значений. Нет ничего меньшего, так как char-это полный байт, если только вы не решите хранить несколько значений в одной переменной путем разбиения битов... Удачи вам!

char является узким целочисленным типом. Он может быть как подписанным, так и неподписанным. Если он не подписан, его диапазон составляет по крайней мере от 0 до 255; если он подписан, его диапазон составляет по крайней мере от -127 до +127. (Да, -127, а не -128; стандарт не требует дополнения 2 для целых чисел со знаком).

Тип char, как следует из названия, в первую очередь предназначен для хранения символов, но вы можете использовать его для хранения небольших целых чисел, если хотите, особенно если вы знаете, что они будут только в диапазоне от 0 до 127. Наверное, так будет лучше. использовать unsigned char или signed char.

Но в любом случае не ожидайте, что экономия пространства будет значительной по сравнению с использованием int. Многие системы требуют больше и медленнее кода для выполнения арифметики на значениях char, чем на значениях int, а значения char в любом случае неявно повышаются до int в большинстве случаев. Если вам нужно хранить большой массив малых целочисленных значений, имеет смысл использовать массив некоторого символьного типа. Для одной переменной использование char вместо int не сильно сэкономит, если что-нибудь.

Вы также должны иметь в виду, что int гарантированно должно быть не менее 16 бит, а не 32. (Но в наши дни он, вероятно, будет 32 бит или шире в большинстве систем, которые вы, вероятно, используете, если вы не делаете встроенную работу.) Если вам нужен определенный размер, существует ряд типов (собственно typedefs, псевдонимы для существующих типов), определенных в <stdint.h>.

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

В общем

1) Использование int (или unsigned) - это наилучшая скорость и наименьший размер кода.

2) Используйтенаименьший целочисленный тип char, signed char, или unsigned char), поскольку они используют наименьшее пространство памяти. Нет ни одного типа меньше, за исключением, может быть, _Bool , который не будет работать для 0 до 4. Битовые поля потенциально меньше, если у вас есть несколько таких полей. небольшие предметы, которые нужно упаковать вместе.

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


Как упоминают многие о char предположениях:

1) оно либо подписано, либо не подписано.

2) он имеет минимальную ширину 8 бит иминимальную ярость от 0 до 255или -127 до 127. (не -128)