使用 union 进行类型双关是不可移植的(尽管与任何其他类型双关方法相比并不特别不便携)。
例如,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);
};
是的,理论上我们可以在这里使用结构体而不是联合体——但除了浪费内存之外,它没有任何意义。文件中的字体定义只定义了一种字体。除了它实际定义的字体之外,让它生成一个包含菜单定义、图标定义、数字、字符串等的结构是没有意义的。[编辑结束]
当然,使用联合来节省内存已经不再那么重要了。虽然现在通常看起来相当微不足道,但当 64 Kb 的 RAM 很多时,内存节省意味着更多。