使用联合进行类型双关是不可移植的(尽管与任何其他类型双关方法相比并不特别不便携)。
OTOH,例如一个解析器,通常有一个联合来表示表达式中的值。
[编辑:我将解析器示例替换为我希望更易于理解的示例]:
让我们考虑一个 Windows 资源文件。您可以使用它来定义菜单、对话框、图标等资源。像这样:
#define mn1 2
mn1 MENU
{
MENUITEM "File", -1, MENUBREAK
}
ico1 "junk.ico"
dlg1 DIALOG 100, 0, 0, 100, 100
BEGIN
FONT 14, "Times New Roman"
CAPTION "Test Dialog Box"
ICON ico1, 700, 20, 20, 20, 20
TEXT "This is a string", 100, 0, 0, 100, 10
LTEXT "This is another string", 200, 0, 10, 100, 10
RTEXT "Yet a third string", 300, 0, 20, 100, 10
LISTBOX 400, 20, 20, 100, 100
CHECKBOX "A combobox", 500, 100, 100, 200, 10
COMBOBOX 600, 100, 210, 200, 100
DEFPUSHBUTTON "OK", 75, 200, 200, 50, 15
END
解析一个 MENU 给出一个菜单定义;解析 DIALOG 给出一个对话框定义等等。在解析器中,我们将其表示为一个联合:
%union {
struct control_def {
char window_text[256];
int id;
char *class;
int x, y, width, height;
int ctrl_style;
} ctrl;
struct menu_item_def {
char text[256];
int identifier;
} item;
struct menu_def {
int identiifer;
struct menu_item_def items[256];
} mnu;
struct font_def {
int size;
char filename[256];
} font;
struct dialog_def {
char caption[256];
int id;
int x, y, width, height;
int style;
struct menu_def *mnu;
struct control_def ctrls[256];
struct font_def font;
} dlg;
int value;
char text[256];
};
然后我们指定将通过解析特定类型的表达式生成的类型。例如,文件中的字体定义成为联合体的font 成员:
%type <font> font
澄清一下,<font> 部分是指生成的联合成员,第二个“字体”是指将生成该类型结果的解析器规则。以下是针对这种特殊情况的规则:
font: T_FONT T_NUMBER "," T_STRING {
$$.size = $2;
strcpy($$.filename,$4);
};
是的,理论上我们可以在这里使用结构而不是联合——但除了浪费内存之外,它只是没有意义。 only 文件中的字体定义定义了一种字体。除了它实际定义的字体之外,让它生成一个包含菜单定义、图标定义、数字、字符串等的结构是没有意义的。
[编辑结束]
当然,使用联合来节省内存已经不再那么重要了。虽然现在通常看起来相当微不足道,但当 64 Kb 的 RAM 很多时,内存节省意味着更多。