printf的增加了额外的`FFFFFF`为十六进制的字符数组打印 [英] printf adds extra `FFFFFF` to hex print from a char array

查看:263
本文介绍了printf的增加了额外的`FFFFFF`为十六进制的字符数组打印的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑以下简化code波纹管。我想从文件中提取一些二进制数据/流,并将其打印到十六进制格式的标准输出。

我得到了额外的3个字节 0XFFFFFF 。怎么了?从哪儿来的额外的字节来了?

输出

 中:
        2000FFFFFFAF00690033005A00
出:
        2000FFFFFFAF00690033005A00

program.c

 的#include<&stdio.h中GT;
#包括LT&;&stdlib.h中GT;INT主(INT ARGC,字符** argv的){    INT I;
    烧焦原料[10] = {0x20,0x00,0xAF,0x00,0x69,0x00,0x33,0x00,0x5A,0×00};
    FILE * outfile的;
    字符* BUF;    的printf(中:\\ n \\ t的);
    对于(I = 0; I&小于10;我+ +)
        的printf(%02X,原[I]);    OUTFILE = FOPEN(raw_data.bin,W + B);    FWRITE(原始的,1,10,OUTFILE);    BUF =(字符*)malloc的(32 * sizeof的(炭));
    fseek的(OUTFILE,0,SEEK_SET);
    的fread(BUF,1,10,outfile中);    的printf(\\ NOUT:的\\ n \\ t的);
    对于(I = 0; I&小于10;我+ +)
        的printf(%02X,BUF [I]);    的printf(\\ n);    FCLOSE(OUTFILE);
    返回0;
}


解决方案

符号扩展。你的编译器正在实施字符符号字符。当你传递的printf 的字符为他们都被签上自己的promootion期间向 INT 秒。当第一位是0,这并不重要,因为它可以让用 0 s扩展。

0xAF执行二进制是 10101111 由于第一位是一个 1 ,将它传递给时的printf 它与所有的 1 S IN转换扩展到 INT 使其 11111111111111111111111110101111 ,你有十六进制值。

而是使用 unsigned char型来prevent在通话中出现的符号扩展形式

  const的无符号字符原料[] = {0x20,0x00,0xAF,0x00,0x69,0x00,0x33,0x00,0x5A,0×00};

所有你原来的例子,这些值都被符号扩展,它只是 0xAF执行是唯一一个以 1 中的第一位。

同样的行为的另一个简单的例子(假设炭签字)

 的char c = 0xAF执行; //大概给出了一个溢出警告
INT I = C; //额外的24位全部为1
断言(我== 0xFFFFFFAF);

Consider the following simplified code bellow. I want to extract some binary data/stream from a file and print it to the standard output in Hexadecimal format.

I got extra 3 bytes 0xFFFFFF. What's wrong? From where did the extra bytes come?

output

in:
        2000FFFFFFAF00690033005A00
out:
        2000FFFFFFAF00690033005A00

program.c

#include <stdio.h>
#include <stdlib.h>    

int main(int argc, char** argv) {

    int i;
    char raw[10] = {0x20,0x00,0xAF,0x00,0x69,0x00,0x33,0x00,0x5A,0x00};
    FILE *outfile;
    char *buf;

    printf("in:\n\t");
    for( i=0; i<10; i++ )
        printf("%02X", raw[i]);

    outfile = fopen("raw_data.bin", "w+b");

    fwrite(raw, 1, 10, outfile);

    buf = (char *) malloc (32 * sizeof(char));
    fseek(outfile, 0, SEEK_SET);
    fread(buf, 1, 10, outfile);

    printf("\nout:\n\t");
    for( i=0; i<10; i++ )
        printf("%02X", buf[i]);

    printf("\n");

    fclose(outfile);
    return 0;
}

解决方案

Sign extension. Your compiler is implementing char as a signed char. When you pass the chars to printf they are all being sign extended during their promootion to ints. When the first bit is a 0 this doesn't matter, because it gets extended with 0s.

0xAF in binary is 10101111 Since the first bit is a 1, when passing it to printf it is extended with all 1s in the conversion to int making it 11111111111111111111111110101111, the hex value you have.

Instead use unsigned char to prevent the sign extension form occurring in the call

const unsigned char raw[] = {0x20,0x00,0xAF,0x00,0x69,0x00,0x33,0x00,0x5A,0x00};

All of these values in your original example are being sign extended, it's just that 0xAF is the only one with a 1 in the first bit.

Another simpler example of the same behavior (assuming char is signed)

char c = 0xAF; // probably gives an overflow warning
int i = c; // extra 24 bits are all 1
assert( i == 0xFFFFFFAF );

这篇关于printf的增加了额外的`FFFFFF`为十六进制的字符数组打印的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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