【问题标题】:Does this work with void *pointers? If not, how?这适用于 void *pointers 吗?如果没有,怎么办?
【发布时间】:2012-09-12 17:46:01
【问题描述】:

在我们的代码中,我们有一个混合类型的大型结构,并希望为这些类型存储一个重复的 (const) 结构的默认值。

当用户想要默认设置时,最好能够通过获取结构中项目的地址偏移量来做到这一点,然后在“默认”结构中分配具有相同偏移量的值,有点像这样:

void *setting = &settings->thing; // Points to a setting
int offset = setting - &settings;
void *default = &defaults_struct + offset; // Points to the default value
*setting = *default; // Set setting to default value

如果 settings->thing 指向 int8,则从默认值复制 int8 值,但如果 settings->other_thing 是 int32,则复制完整的 32 位。

问题是,这是否适用于如上所述的 void 指针?如果没有,有没有办法做到这一点?我是否错过了实现这一目标的更好方法?

编辑澄清:我们希望将结构中的单个值设置为“默认”结构中的相应值。

【问题讨论】:

  • 为什么不只是settings->thing = defaults_struct->thing
  • 你不能对 void 指针进行指针运算,也不能像那样通过它复制任何东西。您需要使用char* 并确定要复制的适当长度(并自己进行复制)。
  • 您应该使用offsetof 宏来计算偏移量。
  • @interjay,你的意思可能是settings->thing = defaults_struct.thing
  • @interjay - 从更大的角度来看,正在修改的设置将作为指针传递给我们:make_default(void *setting)

标签: c pointers embedded void void-pointers


【解决方案1】:

不,这不起作用。 void * 类型的指针没有与之关联的大小,即不知道它们指向的数据类型。因此,你也不能那样做作业。

您可能应该按照评论中的建议直接从默认值中复制。

还要注意default 是 C 中的保留字,因此您不应该将它用于变量。

如果默认值是全局可见的,您可以定义一个宏来隐藏它:

#define INITIALIZE(s, f) s. f = default_struct. f

用户(我假设是开发人员)现在可以:

struct settings s;

INITIALIZE(s, thing);

也就是说,我(作为开发人员)更喜欢这样的东西:

struct settings s = get_default_settings();

这更清楚,也更少魔法。当然,复制所有字段可能需要更多时间,但设置通常不是性能关键。

请注意,上面的函数可能只是:

struct settings get_default_settings(void)
{
  static const struct settings the_defaults = {/* the default values go here*/};

  return the_defaults;
}

它巧妙地封装了默认值,并删除了全局。

【讨论】:

  • 我可以看到它复制了整个结构,我想只从结构中设置一个值,而其余部分不理会。​​span>
【解决方案2】:

在 C 中没有用于运行时的内置类型/反射信息。为了执行您要求的操作,您需要在运行时知道您正在复制的类型的实际大小。

如果你真的想做你正在做的事情,你需要定义你自己的运行时类型信息,通常通过让每个设置都有自己的结构......类似于......

struct single_setting {
 int stype;
 union {
  uint8_t s8;
  uint16_t s16;
  uint32_t s32;
  uint64_t s64;
  struct {
   char *s;
   size_t len;
  } sstr;
 } u_value;
};

然后编写一个函数来复制和返回这样的值变得相当简单。

如果您只想复制一些设置,这将是相当大的开销,但这几乎是大型配置系统所做的。

【讨论】:

  • 谢谢,为每个设置添加元数据是我一直在玩弄的东西,但确实在嵌入式系统上增加了相当大的开销,特别是因为我们的系统已经建立(需要更新的公平代码库)。我喜欢每个设置都有一个“设置类型”结构的风格。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-12-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-02
  • 2023-03-06
相关资源
最近更新 更多