为什么定宽整数输出字符而不是整数?

4

给定以下代码。

#include <cstdint>
#include <iostream>
#include <limits>

int main()
{
    int8_t x = 5;
    std::cout << x << '\n';

    int y = 5;
    std::cout << y;

    std::cin.clear();
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    std::cin.get();

    return 0;
}

我的输出结果是一个三叶草和数字5。如果固定宽度整数是整数,为什么会输出其数字的ASCII字符符号?
编辑:刚刚发现这种行为只发生在8位固定宽度整数上?这是编译器的行为吗?

std::is_same<std::int8_t, signed char>::value - Ryan Haining
2个回答

12

好的,它们在某种意义上是整数,因为您可以使用它们执行8位整数算术。

但显然在您的系统上,int8_t 被实现为一个到 signed chartypedef。这是完全合法的,因为 signed char 也是整数,但会产生意想不到的结果,因为对于 signed charoperator<< 打印其字符符号而不是其数字值。如果有人尝试打印 signed char 的内容,其他任何结果都会很奇怪。

如果要查看您的 int8_t 的数字值,只需在打印之前进行强制转换为 int


1
谢谢你的回答。他们在 int8_t 上做了一件棘手的事情。 - Wandering Fool
3
我希望存在不透明类型定义... :( - PaperBirdMaster

2
可选的固定宽度类型,如intN_t以及其他一些类型,如uint_fast16_tuintmax_tintptr_t,都是内置整数类型的别名。你不知道它们实际别名的类型是什么,只知道它们必须符合文档约束。
对于“恰好8位”的情况,约束条件并不多,唯一能够为8位宽的整数类型是char类型(记住有三种)。因此,如果存在int8_t,则它必须是charsigned char的别名。
无关地,iostreams 为所有字符类型定义了 operator<< 的重载,其效果是直接将值写入输出而不是将整数格式化为十进制字符串(这样您就可以方便地写 std::cout << 'a'),并且此重载也用于 int8_t——重载决议基于类型而不是类型名称。(也许遗憾的是,有一个 专门的 ostream 重载用于 signed char;更好的做法可能是仅为 char 提供重载,并像普通整数一样处理其他类型。)这就是为什么您在系统编码中看到该值被打印为字符的原因。
如果您想要将该值格式化为字符串进行打印,只需将其转换为其中一种更宽的整数类型即可。例如,您可以使用一元加号应用标准提升: int8_t x = 5; std::cout << +x;

@MSalters:是的。相关措辞在C标准中,这个库组件是从中导入的。术语“带符号整数类型”是一种艺术术语,在“语言/概念/类型”中定义。 - Kerrek SB
@Kerrek SB,我从未听说过在输出中使用+x将char转换为整数。我认为它只是一个多余的一元运算符,明确说明一个值是正数? - Wandering Fool
@WanderingIdiot:C++类型系统令人困惑地复杂。默认提升和算术转换不容忽视 :-S - Kerrek SB
@WanderingIdiot,算术运算符在操作之前会将任何比“int”更窄的整数类型提升为“int”。 - M.M
@MattMcNabb:或者根据情况使用unsigned int - Kerrek SB
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接