我见过很多关于如何实现Base64编码器的例子。但是它们都没有在联合内部使用struct
来完成从三个8位块到四个6位块的转换。而且我想知道为什么没有人使用这种方法,因为对我来说它看起来像一个简单快速的方法。
我在union-struct中写了一个例子。
namespace Base64
{
typedef union
{
struct
{
uint32_t b2 : 0x08;
uint32_t b1 : 0x08;
uint32_t b0 : 0x08;
uint32_t pad : 0x08;
} decoded;
struct
{
uint32_t b3 : 0x06;
uint32_t b2 : 0x06;
uint32_t b1 : 0x06;
uint32_t b0 : 0x06;
uint32_t pad : 0x08;
} encoded;
uint32_t raw;
} base64c_t;
}
我已经测试过使用此方法将0xFC0FC0
或二进制111111000000111111000000
转换为四个6位块,它似乎有效。
Base64::base64c_t b64;
b64.decoded.b0 = 0xFC;
b64.decoded.b1 = 0x0F;
b64.decoded.b2 = 0xC0;
std::cout.fill ( '0' );
std::cout << "0x" << std::hex << std::setw ( 2 ) << b64.encoded.b0 << std::endl;
std::cout << "0x" << std::hex << std::setw ( 2 ) << b64.encoded.b1 << std::endl;
std::cout << "0x" << std::hex << std::setw ( 2 ) << b64.encoded.b2 << std::endl;
std::cout << "0x" << std::hex << std::setw ( 2 ) << b64.encoded.b3 << std::endl;
输出:
0x3f
0x00
0x3f
0x00
这种将8位块转换为6位块的方法是否存在缺点?或者还没有人提前考虑过这种方式?
答案 0 :(得分:2)
在结构中打包位域的顺序是实现定义的。因此,虽然您在 计算机上获得了正确的base64结果,但是当您将此代码移植到不同的体系结构或编译器(例如,big-endian PowerPC)时,您可能会得到完全不同的(错误!)答案。借用this answer:
未指明的行为
- 分配用于保存位字段(6.7.2.1)的可寻址存储单元的对齐。
实施定义的行为
- 位字段是否可以跨越存储单元边界(6.7.2.1)。
- 单位内的位域分配顺序(6.7.2.1)。
因此,您最好使用位移代码(这基本上是每个base64实现所使用的代码),因为这将保证跨平台的相同。