背景:这个问题是这个问题的后续。
给定的答案建议通过unsigned char *
而不是char*
成功访问数据。
主要问题:但是如果我们别无选择,我们该怎么办?(即,如果char*
由函数原型强加)。
语境:
假设我们已将int
二进制格式的数组写入文件。
它可能看起来像(没有错误检查):
const std::string bin_file("binary_file.bin");
const std::size_t len(10);
int test_data[len] {-4000, -3000, -2000, -1000, 0, 1000, 2000, 3000, 4000, 5000};
std::ofstream ofs(bin_file, std::ios::trunc | std::ios::binary);
for(std::size_t i = 0; i < len; ++i)
{
ofs.write(reinterpret_cast<char*>(&test_data[i]), sizeof test_data[i]);
}
ofs.close();
现在我想打开文件,读取它,将之前写入的数据一一打印出来。
打开如下执行(不检查错误):
std::ifstream ifs(bin_file, std::ios::binary); // open in binary mode
// get the length
ifs.seekg(0, ifs.end);
std::size_t byte_size = static_cast<std::size_t>(ifs.tellg());
ifs.seekg(0, ifs.beg);
此时,byte_size == len*sizeof(int)
。
可能的解决方案:
我知道我可以通过以下方式做到这一点:
int val;
for(std::size_t i = 0; i < len; ++i)
{
ifs.read(reinterpret_cast<char*>(&val), sizeof val);
std::cout << val << '\n';
}
或通过:
int vals[len];
ifs.read(reinterpret_cast<char*>(vals), static_cast<std::streamsize>(byte_size));
for(std::size_t i = 0; i < len; ++i)
std::cout << vals[i] << '\n';
这两种解决方案都可以正常工作,但它们都不是这个问题的目的。
问题描述:
我在这里考虑我想将完整的二进制文件内容放入 achar*
并在之后处理它的情况。
我不能使用,unsigned char*
因为std::ifstream::read()
期待char*
.
我试过了:
char * buff = new char[byte_size];
ifs.read(buff, static_cast<std::streamsize>(byte_size));
int val = 0;
for(std::size_t i = 0; i < len; ++i)
{
// Get the value via std::memcpy works fine
//std::memcpy(&val, &buff[i*sizeof val], sizeof val);
// Get the value via bit-wise shifts fails (guess: signedness issues)
for(std::size_t j = 0; j < sizeof val; ++j)
val |= reinterpret_cast<unsigned char *>(buff)[i*sizeof val + j] << CHAR_BIT*j; // For little-endian
std::cout << val << '\n';
}
delete[] buff;
ifs.close();
通过std::memcpy
将 4 个字节复制到 中int
,我得到了预期的结果(打印val
的 s 与原始值相同)。
通过按位移位,即使使用reinterpret_cast<unsigned char*>
缓冲区,我也会得到垃圾值,导致无法取回原始int
值(打印val
的 s 是“垃圾”值:与原始值不同)。
我的问题是:什么是能够从 a而不是whilestd::memcpy
中取回正确的值,而我的按位移位是不可能的?
我怎么能在不使用(出于一般利益目的)的情况下解决它?我想不通。char*
unsigned char*
std::memcpy