在C / C offsetof宏的合法用途++ [英] Legit Uses of the offsetof Macro in C / C++

查看:131
本文介绍了在C / C offsetof宏的合法用途++的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有是这个宏 offsetof 在C / C ++,让您获得地址在POD结构成员的偏移量。对于从例如Ç常见问题解答

There is this macro offsetof in C/C++ which allows you to get the address offset of a member in a POD structure. For an example from the C FAQ:

struct foo {
int a;
int b;
};

struct foo;

/* Set the b member of foo indirectly */
*(int *)((char *)foo + offsetof(b)) = 0xDEADBEEF;

现在这似乎只是恶我,我不能看到这个宏的许多合法的用途。

Now this just seems evil to me and I can't see many legit uses of this macro.

我见过一个合法的例子是它在的在Linux内核container_of 宏得到一个嵌入式结构的父对象的地址:

One legit example I have seen is it's use in the container_of macro in the Linux Kernel for getting the address of an embedded structures parent object:

/* get the address of the cmos device struct in which the cdev
   structure which inode points to is embedded */
struct cmos_dev *cmos_devp = 
     container_of(inode->i_cdev, struct cmos_dev, cdev);

还有什么其他合法用途是为有此宏?当你要的的使用这个宏?

修改到目前为止,<一个href=\"http://stackoverflow.com/questions/400116/what-is-the-purpose-and-return-type-of-the-builtinoffsetof-operator/400683#400683\">this回答以不同的SO问题是,迄今为止我见过的最好的之一。

EDIT So far this answer to a different SO question is the best one I've seen so far.

推荐答案

嗯......在C,它是在你需要code来描述数据结构的任何地方非常有用的。我已经例如用它做运行时产生的GUI:设置选项■

Well ... In C, it's very useful for any place where you need code to describe a data structure. I've used it e.g. to do run-time-generated GUI:s for setting options.

这工作就像这样:需要的选项定义持有其选项的局部结构,然后介绍了结构以code产生的图形用户界面,使用命令 offsetof 来指明字段。使用偏移而不是绝对地址允许GUI code与结构的任何实例工作,不只是一个。

This worked like this: a command that needs options defines a local structure holding its options, and then describes that structure to the code that generates the GUI, using offsetof to indicate where fields are. Using offsets rather than absolute addresses allows the GUI code to work with any instance of the struct, not just one.

这是有点困难的一个例子(我试过)快速绘制,但由于评论表明的例子是为了,我会再试一次。

This is bit hard to sketch quickly in an example (I tried), but since comments indicate an example is in order, I'll try again.

假设我们有一个自包含的模块,被称为命令,它实现应用程序中的一些动作。此命令有一堆控制其一般行为,应通过一个图形用户界面,被暴露给用户的选项。对于这个例子的目的,假设应用是一个文件管理器,并且该命令可以是例如复制。

Assume we have a self-contained module, called a "command", that implements some action in the application. This command has a bunch of options that control its general behaviour, which should be exposed to the user through a graphical user interface. For the purposes of this example, assume the application is a file manager, and the command could be e.g. "Copy".

这个想法是复制code住在一个C文件,并在另一个GUI code,和GUI code并不需要是硬coded到支持复制命令的选项。相反,我们定义复制文件中的选择,像这样:

The idea is that the copy code lives in one C file, and the GUI code in another, and the GUI code does not need to be hard-coded to "support" the copy command's options. Instead, we define the options in the copy file, like so:

struct copy_options
{
  unsigned int buffer_size;     /* Number of bytes to read/write at a time. */
  unsigned int copy_attributes; /* Attempt to copy attributes. */
  /* more, omitted */
};

static struct copy_options options; /* Actual instance holding current values. */

然后,复制命令与GUI模块注册它的配置设置:

Then, the copy command registers its configuration settings with the GUI module:

void copy_register_options(GUIModule *gui)
{
  gui_command_begin(gui, "Copy");
  gui_command_add_unsigned_int(gui, "Buffer size", offsetof(struct copy_options, buffer_size));
  gui_command_add_boolean(gui, "Copy attributes", offsetof(struct copy_options, copy_attributes));
  gui_command_end(gui);
}

那么,假设用户要求设置复制命令的选项。然后,我们可以先复制当前选项,支持取消,并要求对话控股控制GUI模块在运行时建成,适合编辑此命令的选项:

Then, let's say the user asks to set the copy command's options. We can then first copy the current options, to support cancelling, and ask the GUI module for a dialog holding controls, built at run-time, suitable for editing this command's options:

void copy_configure(GUIModule *gui)
{
  struct copy_options edit = options;

  /* Assume this opens a modal dialog, showing proper controls for editing the
   * named command's options, at the address provided. The function returns 1
   * if the user clicked "OK", 0 if the operation was cancelled.
  */
  if(gui_config_dialog(gui, "Copy", &edit))
  {
    /* GUI module changed values in here, make edit results new current. */
    options = edit;
  }
}

当然,这code假设的设置是纯粹的价值类型,所以我们可以用简单的结构分配复制结构。如果我们还支持动态字符串,我们需要一个函数来完成复制。因为虽然配置数据,任何字符串很可能是最好的pssed在结构中一个静态大小字符阵列,这将是罚款前$ P $。

Of course, this code assumes the settings to be pure value-types, so we can copy the struct using simple struct assignment. If we also supported dynamic strings, we'd need a function to do the copying. For configuration data though, any string would probably best be expressed as a statically-sized char array in the struct, which would be fine.

请注意,该图形用户界面模块仅知道每个值住pssed作为偏移前$ P $事实如何允许我们提供一个临时的堆栈上拷贝的对话框功能。如果我们代替设置了直接指针到每个字段中的图形用户界面模块,这将是不可能的这将是远远不够灵活。

Note how the fact that the GUI module only knows where each value lives expressed as an offset allows us to provide the dialog function with a temporary on-stack copy. Had we instead set up the GUI module with direct pointers to each field, this would not be possible which would be far less flexible.

这篇关于在C / C offsetof宏的合法用途++的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆