在C ++中将十六进制值打印到控制台

时间:2012-06-19 06:39:59

标签: c++

#include <iostream>
#include <iomanip>

using namespace std;

int main()
{
    char array[10];

    for(int i = 0; i<10;i++)
    {
        array[i] = 'a' + i;
    }

    char* test = array;

    printf("%x\n", test);
    cout << hex << test << endl;

}

这个输出是:

bffff94e
abcdefghijN???

为什么不打印相同的东西?

4 个答案:

答案 0 :(得分:6)

cout << hex << test << endl; 

它打印字符串,而不是地址。这是因为operator<<的重载以char const*作为参数,这个重载将参数视为字符串。

如果要打印地址,请将参数强制转换为void*,以便调用其他重载operator<<,这将打印该地址。

cout << hex << static_cast<void*>(test) << endl;

将以十六进制格式打印地址。

请注意,此处不需要hex流操作符,因为地址将以十六进制格式打印。所以

cout << static_cast<void*>(test) << endl;

就够了。

答案 1 :(得分:6)

因为您的程序有未定义的行为。而且因为你问它 打印不同的东西。

您对printf的调用是非法的,导致未定义 行为(并且是一个很好的例子,说明为什么你永远不应该使用printf)。 您的格式说明符表示从中提取unsigned int 参数列表,以十六进制输出。传递它,但是 unsigned int是未定义的行为。碰巧的是,顺便说一句 如果你在一台机器上,通常会实现varargs unsigned和指针的大小相同,你可能会输出 指针的值,将其位视为unsigned。 但是,其他行为肯定是可能的。 (如果我没错的话, g ++将警告这个结构;在某些方面也有可能 平台,它会崩溃。)

std::cout的情况下,您将其传递给char*。根据定义, char*被视为'\ 0'字符串,不是被视为指针(和 当然不是unsigned int)。而且,你还没有定义 行为,因为您的char*未指向'\ 0'终止字符串; 你从来没有把'\ 0'放在最后。 (这可能解释了"N???" 你看到输出的结尾。但同样,未定义的行为是, 好吧,未定义。代码可能很容易崩溃。)

最后,您同时使用printfstd::cout;结果不是 确实指定,除非你在两者之间刷新流。 (实际上,如果您输出到交互式设备,则刷新 输出'\n'字符时应该出现。如果你重定向 输出到文件,但是,你可能会得到不同的东西。)

目前尚不清楚你想要什么。如果要输出地址 array,它将是:

printf( "%p\n", test );
std::cout << static_cast<void*>( test ) << std::endl;

如果要输出已生成的字符串,请附加'\ 0' 它的结尾(没有溢出缓冲区),然后:

printf( "%s\n", test );
std::cout << test << std::endl;

我不确定你要做什么“十六进制”;没有这样的事情 字符串的十六进制表示,以及指针的表示 实施定义,而不是要求考虑任何 在iostream中格式化参数。 (通常,在大多数现代机器上, 它将是十六进制。但是我已经做了很多工作 无论如何,八进制,至少有一个它不仅仅是一个数字 基数。)如果你想要array的十六进制转储,你必须循环, 将每个值输出为十六进制的unsigned

for ( int i = 0; i < 10; ++ i ) {
    printf( "%x", static_cast<unsigned char>( test[i] ) );
}
printf( "\n" );
std::cout.setf( std::ios_base::hex, std::ios::basefield );
for ( int i = 0; i < 10; ++ i ) {
    std::cout << static_cast<unsigned>( static_cast<unsigned char>( test[i] ) );
}
std::cout.setf( std::ios_base::dec, std::ios::basefield );
std::cout << std::endl;

最后:关于演员表的一句话:普通char可以是签名或 无符号;如果已签名,则将其转换为intunsigned,可能会产生负值(int)或非常值 大的正值(unsigned)。于是,第一次转换为 unsigned char,保证[0, UINT_MAX]范围内的结果。 其次,我们必须将unsigned char转换为unsigned

  • printf的情况下,因为我们原本会有未定义的 行为,但转换是隐含的,因为将unsigned char作为vararg传递会自动将其提升为unsigned;以及

  • std::cout的情况下,因为规则是任何字符 type输出为字符,而不是数字值(因为 这里使用的类型是函数重载决策,而不是 传递给vararg或unsigned,没有隐式转换。)

答案 2 :(得分:1)

test本身就是一个指针,即它存储一个地址。您的printf语句打印该地址的十六进制值。

然后cout <<语句打印整个字符串,因为std::hex操纵符不会影响字符串的打印方式。它只会影响整数的打印方式。

你能做的是

  1. 循环遍历数组的字符
  2. 将每个转换为整数并使用std::hex操纵器
  3. 进行打印

    看起来像这样:

    for (int i = 0 ; i < 10 ; ++i)
      std::cout << std::hex << static_cast<int>(array[i]) << '\n';
    

答案 3 :(得分:0)

cout << HEX <<
不能用于char *来打印十六进制字符串, 但你可以将它用于int,double,float等。

而且,当你第二次打印时,为什么字符串有一些乱码是你没有放弃 字符串的'\ n'表示字符串的结尾