因为您的程序具有未定义的行为。因为你要求它打印不同的东西。
您的调用printf
是非法的,并且会导致未定义的行为(并且是一个很好的例子,说明了为什么您永远不应该使用printf
)。您的格式说明符说unsigned int
从参数列表中提取一个,并以十六进制输出。传递它除了 an 之外的任何东西unsigned int
都是未定义的行为。碰巧的是,考虑到 varargs 通常实现的方式,如果你在一台
unsigned
s 和指针大小相同的机器上,你可能会输出指针的值,把它的位当作一个unsigned
. 然而,其他行为当然是可能的。(如果我没记错的话,g++ 会警告这个结构;在某些平台上,它也可能会崩溃。)
在 的情况下std::cout
,您将通过char*
. 根据定义, thechar*
被视为 '\0' 字符串,而不是指针(当然也不是unsigned int
)。再一次,你有未定义的行为,因为你char*
没有指向一个 '\0' 终止的字符串;你永远不会在最后放一个 '\0' 。(这可能解释了"N???"
您在输出末尾看到的情况。但同样,未定义的行为是未定义的。代码很容易崩溃。)
最后,您同时使用printf
and 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;
最后:关于演员表:plainchar
可以是有符号的也可以是无符号的;如果它是有符号的,将其转换为 anint
或 an
unsigned
,可能会产生一个负值 ( int
) 或一个非常大的正值 ( unsigned
)。因此,第一次转换为
unsigned char
,这保证了范围内的结果[0, UINT_MAX]
。其次,当然,我们必须将其转换unsigned char
为unsigned
: