如何在结构中声明填充
How to declare padding in a struct?
我在内存中有一个结构,但并非所有成员都已知(此结构是逆向工程的)。我想做的是在内存中拥有这样的表示形式:
struct Name {
long Id;
byte unknown[32];
float X;
};
但是我希望byte unknown[32]
是不可见的,所以当我使用Name
类型的东西时,我只能看到 2 个变量 Id 和 X。我认为它类似于:
struct Name {
long Id;
byte : 32*8; // So this doesn't appear
float X;
};
但这不起作用 1.因为我被限制为每行 8 个字节,所以它必须看起来像:
struct Name {
long Id;
long long : 64;
long long : 64;
long long : 64;
long long : 64;
float X;
};
其次,当我实际尝试这样做时,它没有按预期工作(访问 X 并不是指结构的偏移0x24)。
你走在正确的轨道上,但你只是把细节弄错了。编译器将对齐填充插入到您的 Name
版本中。此程序可能会执行您想要的操作:
#include <cstddef>
#include <iostream>
#include <cassert>
struct Name {
long Id; // offset 0x00
int : 32; // offset 0x04
long long : 64; // 0x08
long long : 64; // 0x10
long long : 64; // 0x18
int : 32; // offset 0x20
float X; // offset 0x24
};
int main () {
assert(sizeof(int) == 4);
assert(sizeof(long) == 4);
assert(sizeof(float) == 4);
assert(sizeof(long long) == 8);
assert(offsetof(Name, Id) == 0);
assert(offsetof(Name, X) == 0x24);
}
或者,您可以调查#pragma pack
.
注意:没有针对您的问题的便携式标准认可的解决方案。编译器可以自由地(几乎)在他们选择的任何地方和方式插入填充字节。但可能存在不可移植的、编译器认可的解决方案,例如上面的两个。
如果您正在寻找任何未知结构的通用解决方案,请查看此代码
template <size_t SIZE> class UnknownStruct
{
public:
enum {size = SIZE};
explicit UnknownStruct(unsigned char* data)
{
memcpy(m_data, data, SIZE);
}
template <size_t OFFSET, typename TYPE> TYPE* read()
{
if(OFFSET + sizeof(TYPE) <= SIZE)
return reinterpret_cast<TYPE*>(m_data + OFFSET);
return NULL;
}
private:
unsigned char m_data[SIZE];
};
未知结构是一团原始字节(计数大小),您可以使用read
函数访问。下面是如何将其用于解决问题的示例
class Name : public UnknownStruct<sizeof(long) + 32 + sizeof(float)>
{
public:
explicit Name(unsigned char* data) : UnknownStruct<size>(data){}
long& ID()
{
return *read<0, long>();
}
float& X()
{
return *read<sizeof(long) + 32, float>();
}
};
调用代码如下所示
unsigned char foodata[100] = {0};
Name fooreader(foodata);
fooreader.ID() = 57;
long id = fooreader.ID();
当您发现有关结构的更多信息时,可以向 Name 类添加更多函数,这些函数将从适当的偏移量读取类型
此代码的优点是它可以用于任何未知结构。可能还有其他库提供此解决方案,但这简短而简单,可以使用
相关文章:
- .cpp和.h文件中的模板专用化声明
- 在c++中用vector填充一个简单的动态数组
- 未在作用域中声明unordered_map
- C++避免重复声明的语法是什么
- 如何确保C++函数在定义之前声明(如override关键字)
- 错误:未在此范围内声明'reverse'
- 如何使用用户输入在C++中正确填充2D数组
- 奇怪的(对我来说)返回声明 - 在谷歌上找不到任何关于它的信息
- 为什么在定义函数之前先声明它
- 如何声明特征矩阵,然后通过嵌套循环初始化它
- #ifdef和未声明的标识符
- 如何找到大小'x'数组是否完全填充,在C++?
- 声明数组已经填充了零
- 声明一个类型为String的数组,该数组包含带填充的数字
- 如何在C++中声明带有已填充信息的指针
- 声明一个表,然后填充一个表
- 如何在结构中声明填充
- 在头文件中声明要由 .cc 文件访问和填充的结构
- 如何在创建后正确填充对象而不修改类声明
- (Qt C++)用值填充QMap,同时声明/初始化