使用printf以十六进制格式打印字符串,结果失真

mis*_*yes 4 c printf

我想以十六进制格式打印字符串,

在机器A上,类似于

ori_mesg = gen_rdm_bytestream (1400,seed)
sendto(machine B, ori_mesg, len(mesg))
Run Code Online (Sandbox Code Playgroud)

在机器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");
Run Code Online (Sandbox Code Playgroud)

seed 在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;
}
Run Code Online (Sandbox Code Playgroud)

但是我得到了printf的结果:

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
Run Code Online (Sandbox Code Playgroud)

要么

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 
Run Code Online (Sandbox Code Playgroud)

为什么有这么多fffffmesg_check

这种现象有什么潜在的原因吗?谢谢!

Kei*_*son 17

这是一个小程序,说明了我认为您可能遇到的问题:

#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;
}
Run Code Online (Sandbox Code Playgroud)

在我的系统上(在plain char上签名),我得到了这个输出:

  0 10 7f ffffff80 ffffffff
Run Code Online (Sandbox Code Playgroud)

的值255,存储在(符号)时char,被存储为-1.在printf通话中,它被提升为(已签名)int- 但"%2x"格式告诉printf它将其视为一个unsigned int,因此显示fffffffff.

确保您的mesgmesg_check数组被定义为数组unsigned char,而不是普通数组char.

更新:一年多后重读这个答案,我意识到这不太正确.这是一个在我的系统上正常运行的程序,几乎肯定可以在任何合理的系统上运行:

#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;
}
Run Code Online (Sandbox Code Playgroud)

输出是:

 00 10 7f 80 ff
Run Code Online (Sandbox Code Playgroud)

类型的参数unsigned char被提升为(带符号)int(假设它int可以包含所有类型的值unsigned char,即INT_MAX >= UCHAR_MAX实际上所有系统都是如此).所以参数arr[i]被提升为int,而" %02x"格式需要一个类型的参数unsigned int.

C标准强烈暗示,但并不完全陈述,相应的有符号和无符号类型的参数是可互换的,只要它们在两种类型的范围内 - 这就是这里的情况.

完全正确,您需要确保参数实际上是类型unsigned int:

printf("%02x", (unsigned)arr[i]);
Run Code Online (Sandbox Code Playgroud)

  • +1 这确实是发生的事情,但最简单的方法就是掩盖所有垃圾,例如 `printf(" %2x", arr[i] &amp; 0xFF);` (2认同)