为什么 int8 像 char (C++) 一样工作(Visual Studio 2015)

Why int8 works like char (C++) (Visual Studio 2015)

我试图在 C++ 中找到最小的 int 类型。我读到没有使用少于一个字节的类型,because is the minimum addressable size。我找到的最小的是int8_t,或者_int8visual studio类型。我尝试同时使用两者,但程序将值存储为字符。有一种方法可以将这种类型用作整数吗?或者甚至,如果有办法使用更小的类型(2 位(有符号)将是完美的 XD,我只需要存储 -1、0 和 1)或任何其他数字字节类型。

提前致谢

标准为您提供以下类型:

  • signed char
  • unsigned char

char 相当于其中之一)

而您在 8 位系统上的固定宽度 int8_tuint8_t 只是这些的 别名

都已经是整数了

您的陈述 "but the program stores the values as chars" 表明人们误解了这些类型的基本价值 。这可能是由于以下原因。

您可能遇到的唯一 "problem" 是 IOStreams 子库中这些类型的特殊格式:

const char c = 40;
std::cout << c << '\n';
// Output: "("

因为 int8_t is/may 是 signed char,这在字面上是一样的:

const int8_t c = 40;
std::cout << c << '\n';
// Output: "("

但这很容易 "fixable" 一点积分提升:

const char c = 40;
std::cout << +c << '\n';
// Output: 40

现在流得到一个 int,并将其作为其格式化例程的一部分进行词法转换。

这与标准库提供的类型系统和函数重载有关;它与 "how the values are stored" 无关。都是整数。

您可以使用带两位的 bit field

I tried to use both, but the program stores the values as chars.

它不会(将值存储为字符)。在 C++ 中,char 值 整数值。与其他整数类型的不同之处在于两个地方:

  • 编译器透明地将字符文字转换为整数

  • 标准库将 char 类型与其他整数类型分开处理(也就是说,它认为 char 代表 字母 文本字符,而不是数字)。

就编译器而言,代码:

char x = 'A';

相当于:

char x = 65; // set value to 65 (ASCII code for letter "A")

如果您在调试器中查看 x 的第二个定义,debugger/IDE 可能会告诉您 x 是 'A'。

Or even, if there are a way to use smaller types (2 bits (signed) would be perfect XD, I need to store only -1, 0 and 1), or any other numeric byte type.

没有小于 8 位表示的整数类型。

也就是说,您可以(并且可能应该)为其创建自定义类型:

enum class your_type: std::uint8_t
{
    negative = -1,
    neutral = 0,
    positive = 1
};

选择在您的程序上下文中有意义的值(即不是 "negative, neutral and positive")。

对于 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()