使用printf打印十六进制格式的字符串,结果失真 [英] Use printf to print character string in hexadecimal format, distorted results
问题描述
我想在机器 A 上以十六进制格式打印一个字符串.例如:
I want to print a character string in hexadecimal format on machine A. Something like:
ori_mesg = gen_rdm_bytestream (1400, seed)
sendto(machine B, ori_mesg, len(mesg))
在机器 B 上
recvfrom(machine A, mesg)
mesg_check = gen_rdm_bytestream (1400, seed)
for(i=0;i<20;i++){
printf("%02x ", *(mesg+i)& 0xFF);
}
printf("\n");
for(i=0; i<20; i++){
printf("%02x ", *(mesg_check+i));
}
printf("\n");
seed
在 1, 2, 3, ...
seed
varies among 1, 2, 3, ...
字节生成函数为:
u_char *gen_rdm_bytestream (size_t num_bytes, unsigned int seed)
{
u_char *stream = malloc (num_bytes+4);
size_t i;
u_int16_t seq = seed;
seq = htons(seq);
u_int16_t tail = num_bytes;
tail = htons(tail);
memcpy(stream, &seq, sizeof(seq));
srand(seed);
for (i = 3; i < num_bytes+2; i++){
stream[i] = rand ();
}
memcpy(stream+num_bytes+2, &tail, sizeof(tail));
return stream;
}
但我从 printf 得到的结果如下:
But I got results from printf like:
00 01 00 67 c6 69 73 51 ff 4a ec 29 cd ba ab f2 fb e3 46 7c
00 01 00 67 ffffffc6 69 73 51 ffffffff 4a ffffffec 29 ffffffcd ffffffba ffffffab fffffff2 fffffffb ffffffe3 46 7c
或
00 02 88 fa 7f 44 4f d5 d2 00 2d 29 4b 96 c3 4d c5 7d 29 7e
00 02 00 fffffffa 7f 44 4f ffffffd5 ffffffd2 00 2d 29 4b ffffff96 ffffffc3 4d ffffffc5 7d 29 7e
为什么mesg_check
有这么多fffff
?
这种现象是否有任何潜在的原因?
Are there any potential reasons for this phenomenon?
推荐答案
这是一个小程序,它说明了我认为您可能遇到的问题:
Here's a small program that illustrates the problem I think you might be having:
#include <stdio.h>
int main(void) {
char arr[] = { 0, 16, 127, 128, 255 };
for (int i = 0; i < sizeof arr; i ++) {
printf(" %2x", arr[i]);
}
putchar('\n');
return 0;
}
在我的系统上(对纯 char
进行签名),我得到以下输出:
On my system (on which plain char
is signed), I get this output:
0 10 7f ffffff80 ffffffff
值 255
存储在(有符号的)char
中时,存储为 -1
.在 printf
调用中,它被提升为(签名)int
-- 但 "%2x"
格式告诉 printf
> 将其视为 unsigned int
,因此它显示 fffffffff
.
The value 255
, when stored in a (signed) char
, is stored as -1
. In the printf
call, it's promoted to (signed) int
-- but the "%2x"
format tells printf
to treat it as an unsigned int
, so it displays fffffffff
.
确保您的 mesg
和 mesg_check
数组被定义为 unsigned char
数组,而不是普通的 char
.
Make sure that your mesg
and mesg_check
arrays are defined as arrays of unsigned char
, not plain char
.
更新: 一年多后重读这个答案,我意识到它不太正确.这是一个可以在我的系统上正常运行的程序,并且几乎肯定可以在任何合理的系统上运行:
UPDATE: Rereading this answer more than a year later, I realize it's not quite correct. Here's a program that works correctly on my system, and will almost certainly work on any reasonable system:
#include <stdio.h>
int main(void) {
unsigned char arr[] = { 0, 16, 127, 128, 255 };
for (int i = 0; i < sizeof arr; i ++) {
printf(" %02x", arr[i]);
}
putchar('\n');
return 0;
}
输出为:
00 10 7f 80 ff
unsigned char
类型的参数被提升为(有符号)int
(假设 int
可以保存 类型的所有值unsigned char
,即 INT_MAX >= UCHAR_MAX
,实际上所有系统都是这种情况).所以参数 arr[i]
被提升为 int
,而 " %02x"
格式需要一个 unsigned int 类型的参数代码>.
An argument of type unsigned char
is promoted to (signed) int
(assuming that int
can hold all values of type unsigned char
, i.e., INT_MAX >= UCHAR_MAX
, which is the case on practically all systems). So the argument arr[i]
is promoted to int
, while the " %02x"
format requires an argument of type unsigned int
.
C 标准强烈暗示,但没有完全直接声明,相应的有符号和无符号类型的参数可以互换,只要它们在两种类型的范围内 - 即案例在这里.
The C standard strongly implies, but doesn't quite state directly, that arguments of corresponding signed and unsigned types are interchangeable as long as they're within the range of both types -- which is the case here.
要完全正确,您需要确保参数实际上是 unsigned int
类型:
To be completely correct, you need to ensure that the argument is actually of type unsigned int
:
printf("%02x", (unsigned)arr[i]);
这篇关于使用printf打印十六进制格式的字符串,结果失真的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!