【问题标题】:Using a pointer for casting char* to unsigned char*使用指针将 char* 转换为 unsigned char*
【发布时间】:2015-03-31 05:48:21
【问题描述】:

我正在编写一些使用 fstream read() 函数的代码,该函数需要一个 char* 作为缓冲区。稍后,我想将此缓冲区中的字节用作无符号字符,所以我要么必须:1. 将缓冲区声明为 char*,然后稍后为每个元素执行 static_casts,2. 声明缓冲区作为 unsigned char* ,然后在我将其传递给 read 函数时执行 reinterpret_cast,或者 3. 将缓冲区声明为 char* 并创建一个转换指针,用于将缓冲区作为 unsigned char 访问。

这是一个sn-p:

char* buf = new char[512];
unsigned char* ubuf = reinterpret_cast<unsigned char*>(buf);

    fstream myfile;

    myfile.open("foo.img");

    myfile.seekg(446);
    myfile.read(buf, 16);
    //myfile.read(reinterpret_cast<char*>(buf), 16);

int bytes_per_sector = ubuf[1] << 8 | ubuf[0];
...

我喜欢这种方式,因为我只需要转换一次,我可以访问缓冲区作为任一类型,而无需每次都进行转换。但是,这是一个好习惯吗?这里有什么可能出错的地方吗?使用 reinterpret_cast 让我有点紧张,因为我通常不使用它,而且我被告知要小心使用它很多次。

【问题讨论】:

  • 这是reinterpret_cast 实际上安全且有意义的极少数情况之一。
  • @Deduplicator 呃。请不要推荐使用 C-style casts。请考虑在 C++ 中已弃用的那些。 在这种情况下是安全的,但是直接禁止它们并避免潜在的混淆是一个更简单的规则。而reinterpret_cast,更明确,也使代码更具可读性,因为它清楚地告诉读者正在执行哪个演员。
  • @Deduplicator C++ 强制转换 replace C 强制转换。使用 C 强制转换既无用也不合理,因为总是有更具体的 C++ 强制转换。没有理由使用 C 强制转换。您的“可能不够笨重”是没有意义的,因为 1. C 演员表只会做适当的 C++ 演员表所做的事情,而 2. 在这种情况下,这没什么。
  • @Deduplicator philipxy 和我的观点是reinterpret_cast 是明确的,因此即使不是类型安全也可以提高可读性。 reinterpret_cast 具有明确定义的含义。相比之下,C 风格的演员表则不然。它可以表示许多事物中的任何一种,因此在代码中使用它会掩盖读者的实际语义。这通常被认为是一个非常糟糕的主意。
  • ... 现在,如果我必须重新设计 C++,我希望将 c-style-cast 降级为隐式,函数式降级为隐式+任何 ctor+conversion-operator(这是羞耻 implicit_cast 不在 C++14 中),并使其他 4 种(静态、常量、动态、重新解释)简短而简洁的变体。

标签: c++ pointers fstream reinterpret-cast


【解决方案1】:

在这种情况下,reinterpret_cast 很好,原因有两个:

  1. (签名的)charunsigned char 类型必须具有相同的 "representation and alignment"。这意味着数据不会有差异(它将是每位精确的),或者缓冲区被解释为多长时间。

  2. 文件读取函数通常使用char* 作为通用数据访问类型。他们不能使用void*,因为void 类型具有特别未定义的长度和表示。但是,char 确实如此。所以他们可以用它来读/写一系列字节。

实际上,文件函数通常旨在将数据重新解释为/来自其他事物。它允许您拥有像

这样的结构
typedef struct structSomeStruct
{
    char name[8]; // a basic, fixed length, string
    unsigned long i; // a 32 bit value
    float x, y, z, w;
} SomeStruct;

或者

class SomeStruct
{
    public:
        char name[8];
        unsigned long i;
        float x, y, z, w;
        
        SomeStruct()
        {
            // ...
        }
};

并使用以下方式将其存储到文件中:

SomeStruct st;

// populate the st data structure

// file.write(char* start_of_data, size_t number_of_bytes);
file.write(reinterpret_cast<char*>(&st), sizeof(SomeStruct));

并以类似方式阅读。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-10-19
    • 2013-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多