因为您的程序有未定义的行为,因为您要求打印不同的内容。
您调用的printf是非法的,并导致未定义的行为(这是为什么您永远不应该使用printf的很好的例子)。您的格式说明符指定从参数列表中提取一个unsigned int,并以十六进制输出该值。传递除unsigned int之外的任何内容都是未定义的行为。发生这种情况时,由于可变参数通常的实现方式,如果您在一个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:
1.对于printf,因为否则我们会有未定义的行为,但是转换是隐式的,因为将unsigned char作为vararg传递会自动将其提升为unsigned。
2.对于std :: cout,规则是任何字符类型都应该被输出为字符,而不是数值(由于类型在此处用于函数重载解析,并且不被传递给vararg或unsigned,因此没有隐式转换)。
printf()
中使用%p
,而%x
是用于无符号十六进制整数的。类似于%x
,std::hex
对于指针不会按照你的期望工作,它旨在与整数值一起使用。 - Guillaume Papin