printf 将额外的 `FFFFFF` 添加到字符数组的十六进制打印 [英] printf adds extra `FFFFFF` to hex print from a char array
问题描述
考虑下面的简化代码.我想从文件中提取一些二进制数据/流,并以十六进制格式将其打印到标准输出.
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.
我得到了额外的 3 个字节 0xFFFFFF
.怎么了?额外的字节从哪里来?
I got extra 3 bytes 0xFFFFFF
. What's wrong? From where did the extra bytes come?
输出
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;
}
推荐答案
符号扩展.您的编译器将 char
实现为 signed char
.当您将字符传递给 printf
时,它们都在升级到 int
期间进行了符号扩展.当第一位是 0 时,这无关紧要,因为它会用 0
s 扩展.
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 promotion to int
s. When the first bit is a 0 this doesn't matter, because it gets extended with 0
s.
0xAF
二进制是10101111
由于第一位是1
,所以当把它传递给printf
时在转换为 int
的过程中扩展了所有 1
使其成为 111111111111111111111111110101111
,您拥有的十六进制值.
0xAF
in binary is 10101111
Since the first bit is a 1
, when passing it to printf
it is extended with all 1
s in the conversion to int
making it 11111111111111111111111110101111
, the hex value you have.
解决方法:使用unsigned char
(而不是char
)来防止调用中出现符号扩展
Solution: Use unsigned char
(instead of char
) to prevent the sign extension from occurring in the call
const unsigned char raw[] = {0x20,0x00,0xAF,0x00,0x69,0x00,0x33,0x00,0x5A,0x00};
原始示例中的所有这些值都进行了符号扩展,只是 0xAF
是唯一一个在第一位带有 1
的值.
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 (live link):
signed char c = 0xAF; // probably gives an overflow warning
int i = c; // extra 24 bits are all 1
assert( i == 0xFFFFFFAF );
这篇关于printf 将额外的 `FFFFFF` 添加到字符数组的十六进制打印的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!