7

这是一个奇怪的问题,一直困扰着我。

该程序是用 C89 编写的,它一次将文件读入 char* 数组 16 个字节(使用 fread 和 sizeof(char) 的大小)。该文件使用“rb”标志打开。然后将该数组传递给一个函数,该函数基本上采用 16 个十六进制值并将其粘贴到一个字符串中,每个值由一个空格分隔。

这就是奇怪的地方。该函数为我拥有的文本文件输入生成一个很好的十六进制转储,一次 16 个字节。但是如果我在一个小的位图图像上尝试它会搞砸——我最终会在字符串中输出 ffffff88 而不是 88。

使用 sprintf("%02x ", input[i]); 将十六进制值放入输出字符串中。在一个循环中。

为什么这适用于某些文件而不适用于其他文件?

4

2 回答 2

12

在 C 中,char 被视为有符号值,除非您将其指定为无符号。似乎当您将参数传递给函数时,当参数恰好是一个字符时,它会被“填充”到常规整数的大小。如果您不知道编译器应该以无符号方式完成此操作,则 128 将变为 0xFFFFFF80,依此类推。

因此,符号扩展发生在打印格式化程序查看值之前。这意味着

printf("%02X", (unsigned) input[i]);

不会解决您的问题,因为 input[i] 的值将被符号扩展,因此从 128 到 255 的所有值都被视为 -127 到 -1 并变为 0xFFFFFF80 到 0xFFFFFF,然后进行转换,而

printf("%02X", ((unsigned char *) input)[i] );

会做的伎俩,但有点笨拙且难以阅读。最好首先使 input[] 的类型为 unsigned char 。

于 2009-11-20T22:19:42.873 回答
9

您看到的是从charto int, usingunsigned char *或 cast to 在强制转换unsigned char为 int 之前(隐式?)执行的符号扩展的结果应该可以解决您的问题。

于 2009-11-20T22:19:37.663 回答