使用printf打印十六进制格式的字符串,结果失真 [英] Use printf to print character string in hexadecimal format, distorted results

查看:53
本文介绍了使用printf打印十六进制格式的字符串,结果失真的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在机器 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.

确保您的 mesgmesg_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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆