#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???
为什么不打印相同的东西?
答案 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???"
你看到输出的结尾。但同样,未定义的行为是,
好吧,未定义。代码可能很容易崩溃。)
最后,您同时使用printf
和std::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
可以是签名或
无符号;如果已签名,则将其转换为int
或
unsigned
,可能会产生负值(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
操纵符不会影响字符串的打印方式。它只会影响整数的打印方式。
你能做的是
std::hex
操纵器看起来像这样:
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'表示字符串的结尾