为什么 fstream.read 和 fstream.write 使用 char 而不是无符号字符?

Why do fstream.read and fstream.write use char and not unsigned char?

本文关键字:fstream 无符号 字符 char read write 使用 为什么      更新时间:2023-10-16

据我所知,read()write()都在那里,所以我们可以直接从文件读取和写入字节,而且我被告知 c++ 中相当于byteunsigned char,那么为什么它们将指针作为参数char呢?

另外,请从我找到的"bmp 文件图像读取器"库中查看此函数:

bool BMPImage::readInfo()
{
//...
//read bmp and dib headers
unsigned char header[28] = {0};
_ifs->read((char*)header, 28);
_width    = *(int*)&header[18]; //width is located in [18] and is 4 bytes size
_height   = *(int*)&header[22]; //height is located in [22] and is 4 bytes size
_bpp      = (unsigned char) *(short*)&header[28]; //bpp is located in [28] and is 2 bytes size
_channels = _bpp / 8; //set num channels manually
//...

为什么_ifs->read()线仍然有效?从未签名字符到字符的转换会强制丢失数据,不是吗?

在 C 和 C++ 中,标准没有指定char是有符号还是无符号,并且实现可以自由地实现它。有单独的类型signed char(保证至少保持范围 [-127,127](和unsigned char(保证至少保持范围 [0,255](,char将等同于其中之一,但它是实现定义的。

鉴于 ASCII 字符集仅包含值 0 到 127,因此从历史上看,单个有符号字节被视为足以保存单个字符,同时仍使用与较大类型相同的约定是有道理的,其中整数类型默认签名,除非显式声明为unsigned

鉴于charunsigned char具有相同的大小,在它们之间转换时应该不会丢失数据。

话虽如此,请记住,fstreamm只是字符std::basic_fstream的专业化:

// from <fstream>
typedef basic_fstream<char>         fstream;

您可以为无符号字符创建自己的类型,如下所示:

typedef basic_fstream<unsigned char> ufstream; 

被教导说,在C++中相当于byteunsigned char

我不知道byte是什么,但你可以用char来表示一个字节就好了。

那么为什么 [fstream.read 和 fstream.write] 将 char 指针作为参数呢?

fstreamstd::basic_fstream<char>的别名。std::basic_fstream是一个模板,其所有操作都处理其指定的char_type。由于该char_typechar,所有操作都处理char,而不是unsigned char

你可以按照胡安的建议使用basic_fstream<unsigned char>,但它比这更复杂。您将需要专门化char_traits<unsigned char>这是basic_fstream<unsigned char>的第二个(默认(模板参数。

从未签名字符到字符的转换会强制丢失数据,不是吗?

不。通过char*访问unsigned char不会丢失任何数据。实际上,通过char*访问任何类型的都不会丢失数据。


另一方面,这:

*(int*)&header[18]

具有未定义的行为,除非缓冲区正确对齐,使得header[18]缓冲区恰好位于int所需的边界处。我在数组的定义中看不到这样的保证。某些体系结构根本不支持未对齐的内存访问。