无法打印无符号字符的cout

26

我正在处理以下代码:

#include<iostream>
#include<stdio.h>

using namespace std;

main() {
    unsigned char a;
    a=1;
    printf("%d", a);
    cout<<a;
}

它正在打印1和一些垃圾。

为什么cout会这样表现呢?


2
一个 unsigned char 不是一个 int。你为什么告诉 printf 它是呢? - chris
发送二进制1到输出接口stout,您会期望得到什么结果? - Udo Klein
2
@chris 在printf调用中,unsigned char将被提升为unsigned,因此该代码是可接受的。 - john
@john,啊,我真傻。我以为有一个无符号字符的,因为有一个字符的,但那样做实际上毫无意义。感谢你澄清了这一点。 - chris
显示剩余2条评论
6个回答

42

cout << a打印的值对您来说可能是垃圾值,但实际上它不是垃圾值。这只是一个非可打印的ASCII字符,无论如何都会被打印出来。请注意,与1对应的ASCII字符是不可打印的。您可以使用std::isprint检查a是否可打印:

std::cout << std::isprint(a) << std::endl;

它将打印0(读作:false),表示该字符不可打印。

--

无论如何,如果您想让cout也打印1,那么请将a转换为以下内容:

cout << static_cast<unsigned>(a) << std::endl;

在C++中用cout打印signed char怎么样?期望的结果是什么,它是如何定义的呢?例如:signed char a = -50; cout << a; - Rajesh
这个代码可以运行,但我在想为什么?难道不应该是 unsigned int 而不仅仅是 unsigned 吗?因为 unsigned 关键字可以与 intfloat 或任何其他内置数据类型一起使用,对吧? - Milan
1
@Milan:unsigned 被编译器翻译为 unsigned int - Nawaz
我更喜欢使用一元加运算符而不是显式转换:std::cout << +a << '\n'; - Cody Gray

16

我曾经有一个类似的问题在这里,但我早已忘记了。解决这个问题可以通过如下方式使用iostreamcout

#include<iostream>
#include<stdio.h>

main() {
    unsigned char a;
    a=1;
    printf("%d", a);
    std::cout<< +a << std::endl;

    return 0;
}

如果你想让cout打印unsigned char值而不是ASCII字符,请不要将其转换回其他类型,你需要对它进行提升

注意我所做的只是在unsigned char之前加上一个+。这是一元加法,会将unsigned char升级,以给出实际的数值表示。

用户Baum mit Augen负责提醒我这个解决方案。


1
那真是锐利的代码 :赞: - caligari

5
您需要将变量a强制转换为整数,使用cout<< (int)(a);。这样,您将在输出中观察到1。使用cout << a;,打印将是与ASCII值1相对应的SOH(起始标题),它无法打印,因此会观察到一些特殊字符。

编辑:

更准确地说,cout语句应该是cout << static_cast<unsigned>(a),正如Nawaz所提到的那样。


3

由于您可以指定输出的类型,因此C编译器有自己的定义打印输出类型的方式。

例如:

uint8_t c = 100;
printf("%d",c);

你可以使用 %dc 以整数形式打印,也可以使用 %c 将其作为字符,%s 打印字符串或 %x 打印十六进制值。

C++ 也有自己的方法,cout 默认将 8 位值作为 char 打印。因此,你必须在输出参数中使用说明符。

你可以使用以下任一选项:

  1. a + before the name of the output argument

    uint8_t data_byte = 100;
    cout << "val: " << +data_byte << endl;
    
  2. use a function cast unsigned(var); like,

     uint8_t data_byte = 100;
     cout << "val: " << unsigned(data_byte) << endl;
    

0

char会与一个数字值相关联。由1表示的字符是SOH报头开始字符,通常不被打印(类似于打印NUL字符\ 0 )。

您可以查看ASCII表以查看将打印哪个字符,但是例如值为65的示例可能有所帮助。其中65是字符A

#include<iostream>
#include<stdio.h>


int main() {
    // initialise with an integer
    char a = 65;

    // print the integer representation
    printf("%d\n", a);

    // print as a character
    std::cout << a << std::endl;

    // initialise with a character 
    char b = 'B';

    // print the integer representation
    printf("%d\n", b);
    std::cout << static_cast<int>(b) << std::endl;
    
    // print as a character
    std::cout << b << std::endl;
}

输出:

65
A
66
66
B

-3

printf("%u",a);

这很简单,试一下吧。

你能再详细解释一下你的答案吗? - Charlie
虽然这段代码可能回答了问题,但提供关于它为什么以及如何回答问题的额外上下文会显著提高其长期价值。请编辑您的答案以添加一些解释。特别是,请解释为什么您认为对于一个“unsigned char”参数,“%u”比“%hhu”更好。 - Toby Speight
这完全没有解决问题(为什么cout::operator<<(unsigned char)将其参数解释为字符而不是算术值?) - Toby Speight

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