使用 C 将十六进制值存储到数组后打印
printing the hex values after storing it to an array using C
我已经完成了从文件中读取并存储为十六进制值(比如第一个值是 D4 C3
)。然后将其存储到 char 数据类型的缓冲区中。但是每当我打印缓冲区时,我都会得到一个像buff[0]=ffffffD4
这样的值; buff[1]=ffffffC3
等等。
如何在不添加任何字节的情况下将实际值存储到缓冲区?
附上这个片段
ic= (char *)malloc(1);
temp = ic;
int i=0;
char buff[1000];
while ((c = fgetc(pFile)) != EOF)
{
printf("%x",c);
ic++;
buff[i]=c;
i++;
}
printf("\n\nNo. of bytes written: %d", i);
ic = temp;
int k;
printf("\nBuffer value is : ");
for(k=0;k<i;k++)
{
printf("%x",buff[k]);
}
您确实在没有添加字节的情况下将实际值存储在缓冲区中。您只是输出带有更多数字的签名数字。这就像您的缓冲区中有“-1”,但您将其输出为“-01”。值是一样的,只是你在输出代码中选择了签名扩展而已。
问题是两件事的结合:
- 首先,当您将较小的类型传递给可变参数函数时,例如
printf
,它会转换为 int
,其中可能包括符号扩展。
- 第二个是您正在使用的格式
"%x"
期望 的相应参数是 和 unsigned int
并将其视为
如果要打印十六进制字符,则使用前缀hh
,如"%hhx"
。
参见例如this printf
(and family) reference 获取更多信息。
最后,如果您只想将读取的数据视为二进制数据,那么您应该考虑使用int8_t
(或者可能是uint8_t
)作为缓冲区。在任何具有 8 位 char
的平台上,它们都是相同的,但会向代码的 reader 提供更多信息(例如 "this is binary data and not a string")。
默认情况下,char
在许多平台上都有签名(标准并不规定其签名)。传递给可变参数列表时,会调用 char
-> int
等标准扩展。如果 char 是无符号的,则 0xd3 仍然是整数 0xd3。如果 char 有符号,则 0xd3 变为 0xffffffd3(对于 32 位整数),因为这是相同的整数值 -45
.
注意如果你没有意识到这一点,你应该重新检查整个程序,因为这样的错误是非常微妙的。我曾经处理过一个工具,该工具只能在强制 -funsigned-char
进入 make 的 CFLAGS
时才能正常工作。 OTOH 这个标志,如果对你可用的话,可能是解决这个问题的一个快速而肮脏的解决方案(但我建议避免使用它以进行更长时间的处理)。
我经常使用的方法是传递给类似 printf() 的函数一个值不是 c
,而是 0xff & c
,它在视觉上易于理解并且对于多个版本来说是稳定的。您可以考虑使用 hh
修饰符(UPD:正如@JoachimPileborg 已经建议的那样),但我不确定所有真正的 C 风格都支持它,包括 MS 和嵌入式。 (MSDN 根本没有列出。)
我已经完成了从文件中读取并存储为十六进制值(比如第一个值是 D4 C3
)。然后将其存储到 char 数据类型的缓冲区中。但是每当我打印缓冲区时,我都会得到一个像buff[0]=ffffffD4
这样的值; buff[1]=ffffffC3
等等。
如何在不添加任何字节的情况下将实际值存储到缓冲区?
附上这个片段
ic= (char *)malloc(1);
temp = ic;
int i=0;
char buff[1000];
while ((c = fgetc(pFile)) != EOF)
{
printf("%x",c);
ic++;
buff[i]=c;
i++;
}
printf("\n\nNo. of bytes written: %d", i);
ic = temp;
int k;
printf("\nBuffer value is : ");
for(k=0;k<i;k++)
{
printf("%x",buff[k]);
}
您确实在没有添加字节的情况下将实际值存储在缓冲区中。您只是输出带有更多数字的签名数字。这就像您的缓冲区中有“-1”,但您将其输出为“-01”。值是一样的,只是你在输出代码中选择了签名扩展而已。
问题是两件事的结合:
- 首先,当您将较小的类型传递给可变参数函数时,例如
printf
,它会转换为int
,其中可能包括符号扩展。 - 第二个是您正在使用的格式
"%x"
期望 的相应参数是 和unsigned int
并将其视为
如果要打印十六进制字符,则使用前缀hh
,如"%hhx"
。
参见例如this printf
(and family) reference 获取更多信息。
最后,如果您只想将读取的数据视为二进制数据,那么您应该考虑使用int8_t
(或者可能是uint8_t
)作为缓冲区。在任何具有 8 位 char
的平台上,它们都是相同的,但会向代码的 reader 提供更多信息(例如 "this is binary data and not a string")。
默认情况下,char
在许多平台上都有签名(标准并不规定其签名)。传递给可变参数列表时,会调用 char
-> int
等标准扩展。如果 char 是无符号的,则 0xd3 仍然是整数 0xd3。如果 char 有符号,则 0xd3 变为 0xffffffd3(对于 32 位整数),因为这是相同的整数值 -45
.
注意如果你没有意识到这一点,你应该重新检查整个程序,因为这样的错误是非常微妙的。我曾经处理过一个工具,该工具只能在强制 -funsigned-char
进入 make 的 CFLAGS
时才能正常工作。 OTOH 这个标志,如果对你可用的话,可能是解决这个问题的一个快速而肮脏的解决方案(但我建议避免使用它以进行更长时间的处理)。
我经常使用的方法是传递给类似 printf() 的函数一个值不是 c
,而是 0xff & c
,它在视觉上易于理解并且对于多个版本来说是稳定的。您可以考虑使用 hh
修饰符(UPD:正如@JoachimPileborg 已经建议的那样),但我不确定所有真正的 C 风格都支持它,包括 MS 和嵌入式。 (MSDN 根本没有列出。)