Почему int8 работает как char (C ++) (Visual Studio 2015)

Я пытаюсь найти самый маленький тип int в C ++. Я читал, что нет типов, которые используют меньше байта, потому что это минимальный адресуемый размер. Самый маленький, который я нашел, это int8_t или _int8 visual studio type. Я пытался использовать оба, но программа хранит значения в виде символов. Есть ли способ использовать эти типы как целые числа? Или даже, если есть способ использовать меньшие типы (2 бита (со знаком) будет идеальным XD, мне нужно хранить только -1, 0 и 1) или любой другой числовой тип байта.

заранее спасибо

-2

Решение

Стандарт дает вам следующие типы:

  • 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и лексически преобразует его как часть процедуры форматирования.

Это связано с системой типов и перегрузками функций, предоставляемыми стандартной библиотекой; это не имеет ничего общего с «как хранятся значения». Все они целые.

3

Другие решения

Я пытался использовать оба, но программа хранит значения в виде символов.

Это не (сохранить значения как символы). В 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
};

Выберите значения, которые имеют смысл в контексте вашей программы (т. Е. Не «отрицательный, нейтральный и положительный»).

2

Вы можете использовать битовое поле с двумя битами.

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()
1
По вопросам рекламы ammmcru@yandex.ru