C++ 在运行时访问任何结构成员
是否可以在不知道结构或类的成员变量名称的情况下访问该结构或类的单个成员? 我想做一个“offsetof(struct,tyname)”,而不需要硬编码结构名或成员变量名。C++ 在运行时访问任何结构成员,c++,c,data-structures,pointers,struct,C++,C,Data Structures,Pointers,Struct,是否可以在不知道结构或类的成员变量名称的情况下访问该结构或类的单个成员? 我想做一个“offsetof(struct,tyname)”,而不需要硬编码结构名或成员变量名。 谢谢。当然可以。如果您有一个结构,并且知道偏移量和成员变量的类型,那么可以使用指针访问它 struct my_struct { int member1; char member2; short member3; char member4; } ... struct my_struct obj
谢谢。当然可以。如果您有一个结构,并且知道偏移量和成员变量的类型,那么可以使用指针访问它
struct my_struct {
int member1;
char member2;
short member3;
char member4;
}
...
struct my_struct obj;
short member3 = *((short*)((char*)&obj + 5));
这将获得member3
的值,在x86计算机上,从obj
的开头开始,该值为5个字节。然而,你要小心。首先,如果结构发生更改,您的数据将成为垃圾。我们到处都在强制转换,因此您没有类型安全性,并且编译器不会在出现错误时警告您。您还需要确保编译器没有打包结构以将变量与字边界对齐,否则偏移量将发生变化
这不是一件令人愉快的事情,如果我是你,我会避免这样做,但是的,这是可以做到的。当然。如果您有一个结构,并且知道偏移量和成员变量的类型,那么可以使用指针访问它
struct my_struct {
int member1;
char member2;
short member3;
char member4;
}
...
struct my_struct obj;
short member3 = *((short*)((char*)&obj + 5));
这将获得member3
的值,在x86计算机上,从obj
的开头开始,该值为5个字节。然而,你要小心。首先,如果结构发生更改,您的数据将成为垃圾。我们到处都在强制转换,因此您没有类型安全性,并且编译器不会在出现错误时警告您。您还需要确保编译器没有打包结构以将变量与字边界对齐,否则偏移量将发生变化
这不是一件愉快的事情,如果我是你,我会避免这样做,但是是的,这是可以做到的。在代码中的某个地方,你需要引用结构中的数据成员。但是,您可以创建一个变量,该变量是指向结构数据成员的指针,从那时起,您不再需要按名称引用它
struct foo
{
int member1;
int member2;
};
typedef int (foo::*intMemberOfFoo);
intMemberOfFoo getMember()
{
if (rand() > RAND_MAX / 2) return &foo::member1;
else return &foo::member2;
}
foo f;
void do_somthing()
{
intMemberOfFoo m = getMember();
f.*m = 0;
}
在代码的某个地方,您需要引用结构中的数据成员。但是,您可以创建一个变量,该变量是指向结构数据成员的指针,从那时起,您不再需要按名称引用它
struct foo
{
int member1;
int member2;
};
typedef int (foo::*intMemberOfFoo);
intMemberOfFoo getMember()
{
if (rand() > RAND_MAX / 2) return &foo::member1;
else return &foo::member2;
}
foo f;
void do_somthing()
{
intMemberOfFoo m = getMember();
f.*m = 0;
}
C和C++是没有内置的“反射”特征的编译语言。这意味着,无论您做什么以及如何做,路径总是从显式硬编码值开始,即成员名称或编译时偏移量值。这意味着,如果您想要基于某个运行时键选择一个结构成员,那么您别无选择,只能手动创建某种映射,将键值映射到标识具体结构成员的对象
在C++中,为了在运行时标识结构成员,可以使用这样的特性作为指向成员的指针。在C中,您唯一的选择是使用偏移值当然,另一个问题是,如果您的成员可以有不同的类型,则指定成员的类型。但是你没有提供详细的信息,所以我不能说你是否需要处理它。 < P> C和C++是没有内置的“反射”特征的编译语言。这意味着,无论您做什么以及如何做,路径总是从显式硬编码值开始,即成员名称或编译时偏移量值。这意味着,如果您想要基于某个运行时键选择一个结构成员,那么您别无选择,只能手动创建某种映射,将键值映射到标识具体结构成员的对象 在C++中,为了在运行时标识结构成员,可以使用这样的特性作为指向成员的指针。在C中,您唯一的选择是使用偏移值
当然,另一个问题是,如果您的成员可以有不同的类型,则指定成员的类型。但是您没有提供有关这方面的详细信息,所以我不能说您是否需要处理它。几年前,我们遇到了一个类似的问题:一个巨大的配置信息结构,我们需要考虑它。因此,我们编写了一个Perl脚本来查找Stutt,解析它的成员,并输出一个看起来像:的C++文件。
struct ConfField
{ const char* name;
int type;
size_t offset;
};
ConfField confFields[] = {
{ "version", eUInt32, 0 },
{ "seqID", eUInt32, 4 },
{ "timestamp", eUInt64, 8 },
// ... lots more ...
{ 0, 0, 0 }
};
我们将使用gcc-E
的输出为脚本提供信息
现在,我知道可以输出一个XML文件,它代表GCC可以编译的任何C++源,因为它实际上使用G+前端来进行解析。所以我建议将它与XML解析脚本配对(我将使用Python和库)来找出你想知道的关于C++源的所有东西。
几年前我们也遇到了类似的问题:我们想反思的一个庞大的配置信息结构。因此,我们编写了一个Perl脚本来查找Stutt,解析它的成员,并输出一个看起来像:
的C++文件。struct ConfField
{ const char* name;
int type;
size_t offset;
};
ConfField confFields[] = {
{ "version", eUInt32, 0 },
{ "seqID", eUInt32, 4 },
{ "timestamp", eUInt64, 8 },
// ... lots more ...
{ 0, 0, 0 }
};
我们将使用gcc-E
的输出为脚本提供信息
现在,我知道可以输出一个XML文件,它代表GCC可以编译的任何C++源,因为它实际上使用G+前端来进行解析。所以我建议将它与XML解析脚本配对(我将使用Python和库)来找出你想知道的关于C++源的所有东西。
< P>技术答案是“是”,因为C++是图灵完成的,只要你足够努力,你几乎可以做任何事情。更实际的答案可能是“不”,因为没有一种安全、简单的方法来做你想做的事情我同意格曼的观点。你到底想做什么让你觉得你需要这个技巧?< /P> < P>技术回答是“是”,因为C++是图灵完成的,只要你足够努力,你几乎可以做任何事情。更实际的答案可能是“不”,因为没有一种安全、简单的方法来做你想做的事情
我同意格曼的观点。你到底想做什么让你觉得你需要这项技术?好吧,你必须先设置一些东西,但这是可以做到的。扩大萨米尔的反应
struct my_struct {
int member1;
char member2;
short member3;
char member4;
}
你可以创建一个表格