嗯……在 C 语言中,它对于任何需要代码来描述数据结构的地方都非常有用。我用过它,例如做运行时生成的 GUI:s 来设置选项。
它的工作原理如下:需要选项的命令定义一个保存其选项的本地结构,然后将该结构描述给生成 GUI 的代码,使用 offsetof 指示字段的位置。使用偏移量而不是绝对地址允许 GUI 代码处理结构的任何实例,而不仅仅是一个。
这有点难以在示例中快速绘制(我尝试过),但由于 cmets 表明示例是有序的,我会再试一次。
假设我们有一个独立的模块,称为“命令”,它在应用程序中实现一些动作。这个命令有一堆选项来控制它的一般行为,这些选项应该通过图形用户界面暴露给用户。出于本示例的目的,假设应用程序是文件管理器,并且命令可以是例如“复制”。
这个想法是复制代码存在于一个 C 文件中,而 GUI 代码存在于另一个文件中,GUI 代码不需要硬编码来“支持”复制命令的选项。相反,我们在复制文件中定义选项,如下所示:
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 模块:
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 模块请求一个对话框,其中包含控件,在运行时构建,适合编辑此命令的选项:
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;
}
}
当然,这段代码假定设置是纯值类型,所以我们可以使用简单的结构赋值来复制结构。如果我们还支持动态字符串,我们需要一个函数来进行复制。不过,对于配置数据,任何字符串可能最好在结构中表示为静态大小的char 数组,这很好。
请注意,GUI 模块只知道每个值的位置(以偏移量表示)这一事实如何允许我们为对话框函数提供临时的堆栈副本。如果我们改为使用指向每个字段的直接指针来设置 GUI 模块,这将是不可能的,而且灵活性会大大降低。