#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)
为什么不打印相同的东西?
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)
足够.
因为您的程序有未定义的行为.而且因为你要求它打印不同的东西.
您的调用printf是非法的,并导致未定义的行为(并且是您不应该使用的一个很好的例子printf).您的格式说明符表示unsigned int从参数列表中提取一个,并以十六进制输出.传递它除了一个unsigned int是未定义的行为.实际上,考虑到通常实现varargs的方式,如果你在一台unsigneds和指针具有相同大小的机器上
,你可能会输出指针的值,将它的位视为一个unsigned.但是,其他行为肯定是可能的.(如果我没弄错的话,g ++会警告这个结构;也有可能在某些平台上,它会崩溃.)
在这种情况下std::cout,你是一个通过它char*.根据定义,它char*被视为'\ 0'字符串,而不是指针(当然不是指针unsigned int).再次,你有未定义的行为,因为你char*没有指向'\ 0'终止的字符串; 你从来没有把'\ 0'放在最后.(这可能解释了"N???"
你在输出结束时看到的内容.但同样,未定义的行为是,未定义.代码可能很容易崩溃.)
最后,您同时使用printf和std::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 char为unsigned:
在这种情况下printf,因为我们否则会有未定义的行为,但转换是隐含的,因为传递unsigned
char一个vararg会自动将其提升为unsigned; 和
在这种情况下std::cout,因为规则是任何字符类型都作为一个字符输出,而不是作为数值输出(并且因为这里的类型在函数重载决策中使用,并且没有被传递给vararg或者unsigned,所以没有隐式转换).