Я пытаюсь найти самый маленький тип int в C ++. Я читал, что нет типов, которые используют меньше байта, потому что это минимальный адресуемый размер. Самый маленький, который я нашел, это int8_t или _int8 visual studio type. Я пытался использовать оба, но программа хранит значения в виде символов. Есть ли способ использовать эти типы как целые числа? Или даже, если есть способ использовать меньшие типы (2 бита (со знаком) будет идеальным XD, мне нужно хранить только -1, 0 и 1) или любой другой числовой тип байта.
заранее спасибо
Стандарт дает вам следующие типы:
signed char
unsigned char
(с char
эквивалентно одному из них)
И ваша фиксированная ширина int8_t
, uint8_t
в 8-битной системе просто псевдонимы для этих.
Все они уже целые числа.
Ваше утверждение «но программа хранит значения в виде символов» предполагает недопонимание того, что значения с этими типами принципиально являются. Это может быть связано со следующим.
Единственная «проблема», с которой вы можете столкнуться, — это специальное форматирование для этих типов в библиотеке IOStreams:
const char c = 40;
std::cout << c << '\n';
// Output: "("
поскольку int8_t
может быть signed char
, это буквально то же самое:
const int8_t c = 40;
std::cout << c << '\n';
// Output: "("
Но это легко «исправить» с помощью небольшого интегрального продвижения:
const char c = 40;
std::cout << +c << '\n';
// Output: 40
Теперь поток получает int
и лексически преобразует его как часть процедуры форматирования.
Это связано с системой типов и перегрузками функций, предоставляемыми стандартной библиотекой; это не имеет ничего общего с «как хранятся значения». Все они целые.
Я пытался использовать оба, но программа хранит значения в виде символов.
Это не (сохранить значения как символы). В C ++ значение char является целочисленное значение. Разница с другими целочисленными типами в двух местах:
компилятор конвертирует символьные литералы в целые числа прозрачно
стандартная библиотека обрабатывает тип char отдельно от других целочисленных типов (то есть считает, что символ представляет буквы текстовые символы, а не цифры).
Что касается компилятора, код:
char x = 'A';
эквивалентно:
char x = 65; // set value to 65 (ASCII code for letter "A")
Если вы посмотрите в отладчике на второе определение x
, вероятно, отладчик / IDE скажет вам, что x это ‘A’.
Или даже, если есть способ использовать меньшие типы (2 бита (со знаком) будет идеальным XD, мне нужно хранить только -1, 0 и 1) или любой другой числовой тип байта.
Не существует целочисленного типа с представлением менее 8 бит.
Тем не менее, вы можете (и, вероятно, должны) создать собственный тип для него:
enum class your_type: std::uint8_t
{
negative = -1,
neutral = 0,
positive = 1
};
Выберите значения, которые имеют смысл в контексте вашей программы (т. Е. Не «отрицательный, нейтральный и положительный»).
Вы можете использовать битовое поле с двумя битами.
С MSVC вы можете использовать #pragma pack(1)
и стремится получить это.
#pragma pack(1)
struct int2 {
int value:2;
};
#pragma pack()
int main()
{
int2 a;
for (int i = 0; i < 10; i++)
{
a.value = i;
std::cout << a.value << std::endl;
}
return 0;
}
Выход:
0
1
-2
-1
0
1
-2
-1
0
1
Я предполагаю, что создание конструкторов и операторных функций для косвенного доступа к значению не должно быть проблемой.
РЕДАКТИРОВАТЬ: Улучшенная версия с операторами:
#pragma pack(1)
template <typename INT_TYPE, int BYTE_SIZE>
class int_x {
INT_TYPE value: BYTE_SIZE;
public:
int_x() :value(0) {}
int_x(INT_TYPE v) :value(v) {}
operator INT_TYPE() const {
return value;
}
int_x& operator=(INT_TYPE v) {
value = v; return *this;
}
int_x& operator+=(INT_TYPE v) {
value += v; return *this;
}
int_x& operator-=(INT_TYPE v) {
value -= v; return *this;
}
int_x& operator/=(INT_TYPE v) {
value /= v; return *this;
}
int_x& operator*=(INT_TYPE v) {
value *= v; return *this;
}
};
typedef int_x<int, 1> int1; //Range [-1;0]
typedef int_x<unsigned int, 1> uint1; //Range [0;1]
typedef int_x<int, 2> int2; //Range [-2;1]
typedef int_x<unsigned int, 2> uint2; //Range [0;3]
typedef int_x<int, 3> int3; //Range [-4;3]
typedef int_x<unsigned int, 3> uint3; //Range [0;8]
#pragma pack()