如何通过cout将一个字符输出为整数?

78
#include <iostream>

using namespace std;

int main()
{  
    char          c1 = 0xab;
    signed char   c2 = 0xcd;
    unsigned char c3 = 0xef;

    cout << hex;
    cout << c1 << endl;
    cout << c2 << endl;
    cout << c3 << endl;
}
我期望的输出如下所示:

ab
cd
ef

然而,我一无所获。

我猜这是因为cout总是将'char'、'signed char'和'unsigned char'视为字符而不是8位整数。但是,'char'、'signed char'和'unsigned char'都是整数类型。

所以我的问题是:如何通过cout将字符输出为整数?

PS:static_cast(...)很丑陋,需要更多的工作来修剪额外的位。


据我所知,强制类型转换是最有效的方法...(例如 static_cast<int>() - Nim
1
顺便说一句,你需要使用"trimming"的唯一原因是明显没有正确使用类型(前两个明显溢出),这就是你得到的结果。如果您始终使用正确的类型,则转换只需使用static_cast<unsigned>(...)... - Nim
2
还有一种选项 cout << +c1; - PlasmaHH
@Nim 你在哪里看到溢出了?这里甚至没有进行任何算术运算,所赋的值只是 0xffffffab0xffffffcd。在具有32位二进制补码整数的系统上,它们被转换为较小的 char,由于二进制补码表示法的特性,它们完美地适合其中。 - Ruslan
@Ruslan 这里没有0xffffffab和0xffffffcd,但是0xab和0xcd对于有符号的char来说太大了,有符号char的最大值为0x7f。是的,位表示法可以允许你这样做,但它是平台相关的,实际上你得到的结果也不一定相同。并非所有平台都使用补码形式。 - Swift - Friday Pie
6个回答

173

2
工作链接:http://www.cs.technion.ac.il/users/yechiel/c++-faq/print-char-or-ptr-as-number.html - GetFree
2
这有点晦涩难懂。像sheu的回答中的简单static_cast明显传达了意图。 - sigy
5
是的,它很难理解,但在通用代码中非常有用。 - Evg
@Evg static_cast 在像“通用代码”这样的地方非常有用,即使没有任意滥用不是每个人都知道的功能,它已经足够难以阅读。无论我自己是否知道这一点,如果大多数人不太可能阅读它,那么它会带来更多的伤害而不是好处。 - user11877195
3
来这里就是为了解决这个问题:正确地从模板化的数值类型发出值。理想情况下,会有一个更明确的运算符,比如 valueOf 或者一个流修饰符,但如果没有这些,一元加号适用于所有数值类型。 关于这种语法的棘手性,这正是语言包含注释的原因,我强烈建议这需要一个简短的注释来说明。 - Steve Hollasch
显示剩余2条评论

10
将它们转换为整数类型,并适当地进行位掩码处理,例如:
``` (int)$variable & $bitmask; ```
#include <iostream>

using namespace std;

int main()
{  
    char          c1 = 0xab;
    signed char   c2 = 0xcd;
    unsigned char c3 = 0xef;

    cout << hex;
    cout << (static_cast<int>(c1) & 0xFF) << endl;
    cout << (static_cast<int>(c2) & 0xFF) << endl;
    cout << (static_cast<unsigned int>(c3) & 0xFF) << endl;
}

2
c1c2的输出是ffffffabffffffcd,这 不是 OP所期望的。 - Mr.C64
然而,'char'、'signed char'和'unsigned char'都是整数类型。static_cast(...)很丑,并需要更多的工作来修剪额外的位。 - xmllmx
@xmllmx:ostream还有一些重载函数,可以将char类型打印为它们的字符表示形式--这不是帖子作者想要的。 - sheu

7
也许是这样的:

char c = 0xab;
std::cout << (int)c;

希望这能有所帮助。

char是一个无符号整数。将其强制转换为int可能会显示奇怪的值。最好将其强制转换为uint8_t。 - RajV
1
不完全正确,uint8_t 是别名。它的实际底层类型是 unsigned char。 此外,char 的符号标记是特定于平台的,因此使用 unsigned charsigned char 类型。 - Gotiasits

2

另一种方法是重载 << 运算符:

#include <iostream>

using namespace std;
typedef basic_ostream<char, char_traits<char>> basicOstream;

/*inline*/ basicOstream &operator<<(basicOstream &stream, char c) {
    return stream.operator<<(+c);
}
/*inline*/ basicOstream &operator<<(basicOstream &stream, signed char c) {
    return stream.operator<<(+c);
}
/*inline*/ basicOstream &operator<<(basicOstream &stream, unsigned char c) {
    return stream.operator<<(+c);
}

int main() {
    char          var1 = 10;
    signed char   var2 = 11;
    unsigned char var3 = 12;
    
    cout << var1 << endl;
    cout << var2 << endl;
    cout << var3 << endl;
    
    return 0;
}

输出以下内容的代码:

10
11
12

Process finished with exit code 0

我认为这非常整洁和有用。希望它能帮到你!

另外,如果您想打印一个十六进制值,可以这样做:
basicOstream &operator<<(basicOstream &stream, char c) {
    return stream.operator<<(hex).operator<<(c);
} // and so on...

1
什么意思?
char c1 = 0xab;
std::cout << int{ c1 } << std::endl;

它简洁安全,且生成与其他方法相同的机器代码。


0

除了使用强制类型转换(int),还可以使用std::hex来完成它:

std::cout << std::hex << (int)myVar << std::endl;

希望它有所帮助。


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