你好,我这里有一个 7 字节的结构,我想将它写入一个 64 位整数。接下来,我想稍后从 64 位整数中提取出这个结构。
对此有什么想法吗?
#include "stdafx.h"
struct myStruct
{
unsigned char a;
unsigned char b;
unsigned char b;
unsigned int someNumber;
};
int _tmain(int argc, _TCHAR* argv[])
{
myStruct * m = new myStruct();
m->a = 11;
m->b = 8;
m->c = 12;
m->someNumber = 30;
printf("\n%s\t\t%i\t%i\t%i\t%i\n\n", "struct", m->a, m->b, m->c, m->someNumber);
unsigned long num = 0;
// todo: use bitwise operations from m into num (total of 7 bytes)
printf("%s\t\t%i\n\n", "ulong", num);
m = new myStruct();
// todo: use bitwise operations from num into m;
printf("%s\t\t%i\t%i\t%i\t%i\n\n", "struct", m->a, m->b, m->c, m->someNumber);
return 0;
}
最佳答案
你应该这样做:
class structured_uint64
{
uint64_t data;
public:
structured_uint64(uint64_t x = 0):data(x) {}
operator uint64_t&() { return data; }
unsigned uint8_t low_byte(size_t n) const { return data >> (n * 8); }
void low_byte(size_t n, uint8_t val) {
uint64_t mask = static_cast<uint64_t>(0xff) << (8 * n);
data = (data & ~mask) | (static_cast<uint64_t>(val) << (8 * n));
}
unsigned uint32_t hi_word() const { return (data >> 24); }
// et cetera
};
(当然,在接口(interface)的细节和 64 位中的组成部分的位置上还有很大的变化空间)
使用不同的类型来别名内存的同一部分通常是一个坏主意。问题是,优化器能够使用如下推理非常有值(value):
"Okay, I've read a
uint64_t
at the start of this block, and nowhere in the middle does the program write to anyuint64_t
s, therefore the value must be unchanged!"
这意味着如果您尝试通过 uint32_t
引用更改 uint64_t
对象的值,它将得到错误的答案。由于这非常依赖于哪些优化是可能的和已完成,实际上很容易在测试用例中永远不会遇到问题,但在您尝试编写的真实程序中会看到它——您将永远尝试找到错误,因为您确信这不是这个问题。
因此,您真的应该使用位旋转(或内在函数,如果分析显示这是一个性能问题并且有可用的可用问题)而不是尝试设置一个聪明的结构来插入/提取字段。
如果您真的知道自己在做什么,我相信您可以使用别名。但只有当您真的知道自己在做什么时才应该这样做,这包括从内到外了解标准的相关规则(我不知道,所以我不能建议您关于如何让它发挥作用)。即便如此,您也可能不应该这样做。
此外,如果您希望整数类型具有特定大小,您应该确实使用正确的类型。例如,切勿将 unsigned int
用于应该正好是 32 位的整数。而是使用 uint32_t
。它不仅是 self 记录的,而且当您尝试在 unsigned int
不是 32 位的环境中构建程序时,您也不会遇到令人讨厌的惊喜。
关于64 位整数中的 C++ 位,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11044254/