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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15823597/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 05:57:48  来源:igfitidea点击:

use printf to print character string in hex format, distorted results

cprintf

提问by misteryes

I want to print character string in hex format,

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

on machine A , something like

在机器 A 上,类似

ori_mesg = gen_rdm_bytestream (1400,seed)
sendto(machine B, ori_mesg, len(mesg))

on machine B

在机器 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");

seedvaries among 1, 2 3....

seed1, 2 3 ....

the bytes generation funcion is:

字节生成函数是:

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;
}

but I got results from printf like:

但我从 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

or

或者

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 

why are there so many ffffffor mesg_check?

为什么有这么多fffffmesg_check

are there any potential reasons for this phenomenon? thanks!

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

回答by Keith Thompson

Here's a small program that illustrates the problem I thinkyou 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;
}

On my system (on which plain charis signed), I get this output:

在我的系统上(在该系统上char签名),我得到以下输出:

  0 10 7f ffffff80 ffffffff

The value 255, when stored in a (signed) char, is stored as -1. In the printfcall, it's promoted to (signed) int-- but the "%2x"format tells printfto treat it as an unsigned int, so it displays fffffffff.

255存储在 (signed) 中时char,存储为-1。在printf调用中,它被提升为 (signed) int- 但"%2x"格式告诉printf将其视为unsigned int,因此它显示fffffffff.

Make sure that your mesgand mesg_checkarrays are defined as arrays of unsigned char, not plain char.

确保您的mesgmesg_check数组被定义为 的数组unsigned char,而不是普通的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;
}

The output is:

输出是:

 00 10 7f 80 ff

An argument of type unsigned charis promoted to (signed) int(assuming that intcan 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.

type 的参数unsigned char被提升为 (signed) int(假设它int可以保存所有 type 的值unsigned char,即 ,INT_MAX >= UCHAR_MAX实际上在所有系统上都是这种情况)。因此参数arr[i]被提升为int,而" %02x"格式需要一个类型为 的参数unsigned int

The C standard strongly implies, but doesn't quitestate 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.

C标准强烈暗示,但不会直接的状态,对应符号和无符号类型的论点是,只要它们是两种类型的范围内互换-这是这里的情况。

To be completelycorrect, you need to ensure that the argument is actually of type unsigned int:

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

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

回答by Akash kumar

Yup, always print string in hex format as:

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

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

you will get error when you try to print

尝试打印时会出错

the whole string in one go and when printing Hex string character by character which using 'Unsigned char' if the string is in format other than 'Unsigned char'

一次打印整个字符串,如果字符串的格式不是“无符号字符”,则在逐个字符打印十六进制字符串时使用“无符号字符”