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

Printing hexadecimal values to console in C++

本文关键字:打印 控制台 十六进制 C++      更新时间:2023-10-16
#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("%xn", test);
    cout << hex << test << endl;
}

此输出为:

bffff94e
abcdefghijN???

为什么它不打印同样的东西?

cout << hex << test << endl; 

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

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

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

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

请注意,这里不需要hex流操纵器,因为地址将以十六进制格式打印。所以

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

就够了。

因为您的程序具有未定义的行为。 因为你要求它打印不同的东西。

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

std::cout的情况下,你已经过去了char*。 根据定义,char*被视为"\0"字符串,而不是指针(和当然不是作为unsigned int)。 再一次,你没有定义行为,因为您的char*不指向以"\0"结尾的字符串;你永远不会在末尾加上"\0"。 (这可能解释了"N???"您会在输出的末尾看到。 但同样,未定义的行为是,好吧,未定义。 代码可能很容易崩溃。

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

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

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

如果要输出生成的字符串,请将"\0"附加到它的末尾(不溢出缓冲区),然后:

printf( "%sn", 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的情况下,因为规则是任何字符类型输出为字符,而不是数值(并且由于类型在函数重载解析中使用,而不是传递给 vararg 或 unsigned ,没有隐式转换)。

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

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

你能做的是

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

那看起来像这样:

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

cout << HEX <<
不能用于字符*来打印十六进制字符字符串,但是您可以将其用于整数,双精度,浮点数等。

而且,当你第二次打印时,为什么字符串有一些乱码,因为你没有给字符串的""表示字符串的结尾