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

ord*_*ary 5 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;

}
Run Code Online (Sandbox Code Playgroud)

这个输出是:

bffff94e
abcdefghijN???
Run Code Online (Sandbox Code Playgroud)

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

Naw*_*waz 6

cout << hex << test << endl; 
Run Code Online (Sandbox Code Playgroud)

它打印字符串,而不是地址.这是因为有过载operator<<这需要char const*作为参数,此重载对待参数作为字符串.

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

cout << hex << static_cast<void*>(test) << endl;
Run Code Online (Sandbox Code Playgroud)

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

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

cout << static_cast<void*>(test) << endl;
Run Code Online (Sandbox Code Playgroud)

足够.

  • @Nawaz 错了。`&amp;test` 打印出别的东西。您的示例使用 *array*,而不是 *pointer*,这就是它起作用但 OP 使用指针的原因。另外,请摆脱这些 C 风格的强制转换。我们有一个广泛的共识,即不应使用它们,这使得它们在教材中更加有害(= 此处)。 (2认同)

Jam*_*nze 6

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

您的调用printf是非法的,并导致未定义的行为(并且是您不应该使用的一个很好的例子printf).您的格式说明符表示unsigned int从参数列表中提取一个,并以十六进制输出.传递它除了一个unsigned int是未定义的行为.实际上,考虑到通常实现varargs的方式,如果你在一台unsigneds和指针具有相同大小的机器上 ,你可能会输出指针的值,将它的位视为一个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;
Run Code Online (Sandbox Code Playgroud)

如果要输出已生成的字符串,则在其末尾添加"\ 0"(不会溢出缓冲区),然后:

printf( "%s\n", test );
std::cout << test << std::endl;
Run Code Online (Sandbox Code Playgroud)

我不确定你要做什么"十六进制"; 没有字符串的十六进制表示,并且指针的表示是实现定义的,并且不需要考虑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;
Run Code Online (Sandbox Code Playgroud)

最后:关于演员的一句话:平原char可以是签名的也可以是未签名的; 如果它已签名,将其转换为a int或an unsigned,可能会产生负值(int)或非常大的正值(unsigned).因此,第一次转换为 unsigned char,保证了范围内的结果[0, UINT_MAX].其次,我们必须转换unsigned charunsigned:

  • 在这种情况下printf,因为我们否则会有未定义的行为,但转换是隐含的,因为传递unsigned char一个vararg会自动将其提升为unsigned; 和

  • 在这种情况下std::cout,因为规则是任何字符类型都作为一个字符输出,而不是作为数值输出(并且因为这里的类型在函数重载决策中使用,并且没有被传递给vararg或者unsigned,所以没有隐式转换).