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

时间:2013-04-04 23:40:12

标签: c printf

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

机器A上的

,类似

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之间有所不同....

字节生成功能是:

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的结果:

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 

为什么fffffmesg_check这么多?

这种现象是否有任何潜在原因? 谢谢!

2 个答案:

答案 0 :(得分: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;
}

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

  0 10 7f ffffff80 ffffffff

存储在(已签名)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;
}

输出结果为:

 00 10 7f 80 ff

unsigned char类型的参数被提升为(已签名)int(假设int可以包含unsigned char类型的所有值,即INT_MAX >= UCHAR_MAX ,几乎所有系统都是如此)。因此,参数arr[i]会提升为int,而" %02x"格式则需要unsigned int类型的参数。

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

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

printf("%02x", (unsigned)arr[i]);

答案 1 :(得分:1)

是的,总是以十六进制格式打印字符串:

for(i=0;till string length;i++)
printf("%02X",(unsigned char)str[i]);

尝试打印时会出现错误

整个字符串一次性打印并且在逐个字符的情况下打印十六进制字符串,如果字符串的格式不是“Unsigned char”,则使用“Unsigned char”