使用二进制数据和无符号字符

working with binary data and unsigned char

本文关键字:无符号 字符 数据 二进制      更新时间:2023-10-16

我正在编写一个程序,读取二进制文件的内容(特别是Windows PE文件、维基百科页面和详细的PE结构(
由于文件中的二进制数据,字符经常"超出"ascii范围(0-127(,从而导致负值。

为了确保我不会使用不需要的负值,我可以传递const unsigned char *,也可以将计算中得到的char转换为unsigned char

一方面,传递const unsigned char *是有意义的,因为数据是具有numaric值的非ascii,因此应该被视为正数
此外,它还允许我执行计算,而无需将结果强制转换为unsigned char
另一方面,如果不先将常量字符串(const char *,如预定义字符串"MZ"、"PE\0\0"等(强制转换为const unsigned char *,则无法将其传递给函数。

在这种情况下,什么是更好的方法或最佳实践?

我想我应该使用unsigned char,但避免强制转换,而是定义一个名为ustring的小类(或类似的类(。你有几个选择。一种是在CCD_ 10上实例化CCD_ 9。这可能很有用(它为您提供了std::string的所有功能,但使用unsigned chars而不是chars。明显的缺点是它可能过于致命,并且与std::string基本上没有兼容性,尽管它几乎完全相同

另一种显而易见的可能性是定义自己的类。既然你显然主要关心字符串文字,我可能会这么做。该类将使用字符串文字进行初始化,并且它将只保存一个指向该字符串的指针,但作为unsigned char *而不仅仅是char *

然后还有一个步骤可以让生活变得更好:定义一个名为_us的用户定义的文字运算符,因此从字符串文字创建您类型的对象将看起来像这样:auto DOS_sig = "MZ"_us;

class ustring {
unsigned char const *data;
unsigned long long len;
public:
ustring(unsigned char const *s, unsigned long long len) 
: data(s)
, len(len)
{}
operator char const *() const { return data; }
bool operator==(ustring const &other) const {
// note: memcmp treats what you pass it as unsigned chars.
return len == other.len && 0 == memcmp(data, other.data, len);
}
// you probably want to add more stuff here.
};
ustring operator"" _us(char const * const s, unsigned long long len) {
return ustring((unsigned char const *)s, len);
}

如果我没有错的话,这应该很容易处理。例如,假设您已经将您认为是PE文件的内容进行了内存映射,其基本地址为mapped_file。要查看它是否有DOS签名,您可以执行以下操作:

if (ustring(&mapped_file[0], 2) == "MZ"_us)
std::cerr << "File appears to be an executable.n";
else
std::cerr << "file does not appear to be an executable.n";

注意:我还没有测试过,所以fencepost之类的错误很可能发生——例如,我不记得传递给用户定义的文字运算符的长度是否包括NUL终止符。这并不是为了表示完成的代码,只是一个可能对探索有用的大致方向的草图。