C++、ifstream 和 char

问题描述 投票:0回答:1

我正在从磁盘读取 PNG 文件并将字节插入到字符向量中,并使用 new 关键字实例化。

打开文件:

std::ifstream file("./images/orange.png", std::ios_base::binary); 

实例化 len 8 (#define PNG_SIGNATURE 8) 的 vec,其中所有元素最初都是空字符:

std::vector<char>* header_buff { new std::vector<char>(PNG_SIGNATURE, ' ') };

将字节写入 vec,其中

f
是对文件的引用,
b
是指向我的 vec 缓冲区的指针:

std::vector<char> chunk_reader(std::vector<char>* b, std::ifstream &f) {

        char c { };

        for(int i { }; i < (*b).size(); ++i) {
            f.get(c);
            (*b)[i] = c;
        };

        return *b;
};

PNG 的第一个字节始终是十六进制

0x89

根据参考资料,

std::ifstream
成员类型是char类型。


我的问题是,在我的实现中:MinGW GCC for Windows,我能够调试我的程序并将PNG的第一个字节视为

signed char
,dec值
-119
。我认为为了便于解析二进制流,我想使用
unsigned char
,所以如果我要
seek
到感兴趣的特定字节,我可以检查它的无符号值在源代码中是否正确,如
 137
而不是它的签名表示。

据我所知,并根据我在这里阅读的类似问题的帖子,cpp 将 char 的 signedness 留给了实现以提高灵活性。因此,如果我插入 gcc 标志

-funsigned-char
,我会得到我期望的行为,并且可以在调试器中直观地看到第一个字节的 dec 值
137

我在这里从更有经验的程序员那里读到,这是一个创可贴,并将类似的内容保留在源代码中以提高可读性,又名从 char 到 unsigned char 的

reinterpreted cast
,据我所知,这是有道理的,因为它们'都是一个字节的信息。

但是后来我看到一些帖子说

reinterpret cast
很 hacky,应该将其留给标准库中设计的用例。

有人可以就这种情况下的最佳实践提供一些建议吗?我最终希望对单个字节执行某些验证,就像在 PNG 的情况下一样,如果命名块的第一个字节是大写或小写 ASCII 字符,那么它将具有特殊含义 - 如果我正在处理,这很简单带有无符号字符,并且可以在源代码中使用十进制值,例如在 switch 语句中。

我对 cpp 很陌生,所以我很感激你的建议。我对设计此类系统的最佳实践和可扩展性感兴趣。

c++ gcc char ifstream signedness
1个回答
0
投票

将向量设置为您需要的类型,并尽早转换 ifstream 输出。

此外,我建议如果这是二进制数据而不是文本,则使用

std::uint8_t
>

std::vector<std::uint8_t> chunk_reader( std::vector<std::uiint8_t>& b,
                                        std::ifstream &f) 
{
    char c { };

    for(int i { }; i < (*b).size(); ++i) 
    {
        f.get(c);
        b[i] = static_cast<std::uint8_t>(c) ;
    }

    return b;
};
© www.soinside.com 2019 - 2024. All rights reserved.