C 十六进制格式给我额外的数字

C hexadecimal formatting giving me extra digits

我一直在开发一个小程序来转储文件的十六进制值,类似于 odhexdump,我 运行 遇到了一个问题打印值。对于某些十六进制值,主要是第二个数字为字母字符的值,它会在打印实际数字之前打印 6 个额外的 f 数字,而不是像我指定的那样只打印一个 2 宽度的值。我已经确认这些值本身在任何方面都不是意外的,是印刷弄乱了它。

代码:

int main(int argc, char* argv[]) {
    FILE* dataFile = fopen(argv[1], "rb");
    int byteCount = 0;
    char currentByte = fgetc(dataFile);
    while (currentByte != EOF) {
        printf("%08d", byteCount);
        do {
            //print as hex
            printf(" %02x ", currentByte);
            //set up for next loop
            currentByte = fgetc(dataFile);
            byteCount++;
        } while (currentByte != EOF && (byteCount) % 16 != 0);
        printf("\n");
    }
    printf("%08d\n", byteCount);
}

输出:

00000000 7f  45  4c  46  02  01  01  00  00  00  00  00  00  00  00  00 
00000016 03  00  3e  00  01  00  00  00  10  6b  00  00  00  00  00  00
00000032 40  00  00  00  00  00  00  00  08  23  02  00  00  00  00  00
00000048 00  00  00  00  40  00  38  00  0d  00  40  00  1f  00  1e  00
00000064 06  00  00  00  04  00  00  00  40  00  00  00  00  00  00  00
00000080 40  00  00  00  00  00  00  00  40  00  00  00  00  00  00  00
00000096 ffffffd8  02  00  00  00  00  00  00  ffffffd8  02  00  00  00  00  00  00
00000112 08  00  00  00  00  00  00  00  03  00  00  00  04  00  00  00
00000128 18  03  00  00  00  00  00  00  18  03  00  00  00  00  00  00
00000144 18  03  00  00  00  00  00  00  1c  00  00  00  00  00  00  00
00000160 1c  00  00  00  00  00  00  00  01  00  00  00  00  00  00  00
00000176 01  00  00  00  04  00  00  00  00  00  00  00  00  00  00  00
00000192 00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00
00000208 fffffff8  34  00  00  00  00  00  00  fffffff8  34  00  00  00  00  00  00

有人知道这里发生了什么吗?

这里有几个问题。

  • char 完全不适合保存原始二进制数据,因为它具有 implementation-defined 符号并且通常是有符号类型,请参阅 Is char signed or unsigned by default?。事实上 char 应该只用于文本字符串。相反,您通常会使用 uint8_t。然而……:
  • EOF 常量的类型为 int,因此如果您打算将某些内容与 EOF 进行比较,则它必须为 int 类型。 fgetc 保证 return 个字符,就好像它们是 unsigned char 但转换为 int - 碰巧的是, int 足够大以容纳一个的所有值unsigned char所以这里可以用int
  • %x printf 的说明符需要 unsigned int.

修复:

  • char currentByte -> int currentByte
  • printf(" %02x ", currentByte); -> printf(" %02x ", (unsigned int)currentByte);.
  • 您必须始终检查 fopen 是否成功,完成后还 fclose 文件指针。另请注意,在专业程序中,直接在没有输入卫生的 argv 上调用 fopen 是不可接受的。您甚至不知道 argv[1] 是否存在 - 程序总体上需要更多的错误处理。