大多数程序可能不可移植
阅读 cmets here,我认为答案是该程序不完全符合 C++ 标准的可移植性。没有程序是。 edit:至少没有程序与网络通信、读取或写入磁盘或期望其他平台回答或更新数据。
C++ 支持平台的硬件,而不是 Java。例如,fgetc 和 fputc 保留往返值,但仅在同一平台上。网络消息之所以有效,是因为每个人都假设一个字节有 8 位。
如果有问题,最好断言平台有 8 位到一个字节:static_assert(CHAR_BIT==8, "Platform must have 8 bits to a byte.");
即使没有断言,也会有其他警钟。一个没有 8 位到一个字节,但仍然通过网络或文件与其他平台通信的平台将比稍后失败,并且将代码移植到它将需要额外的工作来读取和写入假设的 8 位数据 事实上的标准。这看起来很像字节顺序问题,但这里的区别是一方非常明显地赢了。
但它们可以制成便携式
编辑:上面的陈述可能并不总是成立。通过适当的努力,可以使程序变得可移植。以下来自 Mooing Duck 的改编演示了该程序和迭代器如何考虑如何处理不同位数的行为。它显示了具有更多位的系统如何从具有更少位的系统中读取文件。这可以扩展为双向工作:
#include <iterator>
#include <climits>
#include <iostream>
template<class base_iterator, size_t source_bits>
class bititerator : public std::iterator<std::input_iterator_tag, unsigned char> {
mutable base_iterator base;
mutable unsigned char bufferhi;
mutable unsigned char bufferlo;
mutable unsigned char bitc;
public:
bititerator(const base_iterator& b) : base(b), bufferhi(0), bufferlo(0), bitc(0) {}
bititerator& operator=(const bititerator&b) {base = b.base; bufferlo=b.bufferlo; bufferhi=b.bufferhi; bitc=b.bitc; return *this;}
friend void swap(bititerator&lhs, bititerator&rhs) {std::swap(lhs.base, rhs.base); std::swap(lhs.bufferlo, rhs.bufferlo); std::swap(lhs.bufferhi, rhs.bufferhi); std::swap(lhs.bit, rhs.bitc);}
bititerator operator++(int) {bititerator t(*this); ++*this; return t;}
unsigned char* operator->() const {operator*(); return &bufferlo;}
friend bool operator==(const bititerator&lhs, const bititerator&rhs) {return lhs.base==rhs.base && lhs.bitc==rhs.bitc;}
friend bool operator!=(const bititerator&lhs, const bititerator&rhs) {return !(lhs==rhs);}
unsigned char operator*() const {
static_assert(source_bits<CHAR_BIT, "bititerator only works on systems with more bits than the target");
//make sure at least source_bits bits are in the buffers
if (bitc < source_bits) {
bufferhi = static_cast<unsigned char>(*base);
++base;
size_t shift = source_bits-bitc;
bufferlo |= ((bufferhi<<shift)&0xFF);
bufferhi >>= shift;
bitc += CHAR_BIT;
}
return bufferlo;
}
bititerator& operator++() {
operator*();
//shift the buffers down source_bits bits
bufferlo >>= source_bits;
bufferlo |= ((bufferhi<<(CHAR_BIT-source_bits))&0xFF);;
bufferhi >>= source_bits;
bitc -= source_bits;
return *this;
}
};
template<class base_iterator>
bititerator<base_iterator,6> from6bit(base_iterator it) {return bititerator<base_iterator,6>(it);}
bititerator<std::istreambuf_iterator<char>,6> from6bitStart(std::istream& str) {return bititerator<std::istreambuf_iterator<char>,6>{std::istreambuf_iterator<char>{str}};}
bititerator<std::istreambuf_iterator<char>,6> from6bitEnd(std::istream& str) {return bititerator<std::istreambuf_iterator<char>,6>{std::istreambuf_iterator<char>{}};}
#include <fstream>
int main()
{
std::fstream file("binaryfile");
auto end = from6bitEnd(file);
for (auto iter = from6bitStart(file); iter != end; ++iter)
std::cout << *iter;
}