【发布时间】:2021-11-16 04:22:33
【问题描述】:
我正在为一种语言设计抽象语法树 (AST)。我的词法标记看起来像
typedef struct {
tokenHeader header;
tokenData data;
} lexicalToken;
其中tokenHeader 和tokenData 是structs。至于我的 AST 节点,我有一个基本类型:
#define AST_HEADER \
struct astNode *parent; \
tokenHeader header;
typedef struct astNode {
AST_HEADER
} astNode;
以及一些拆分类型。例如,
typedef struct {
AST_HEADER
astNode *nodes[2];
} astTwoSplitNode;
我之所以在AST_HEADER 中不包含tokenData 是因为几乎所有令牌都不使用该字段。这让我想到
typedef struct {
astNode *parent;
lexicalToken token;
// Nodes which use tokenData are always terminal nodes.
} astNodeWithData;
这终于让我想到了我的问题:astNodeWithData 的排列方式是否保证我可以将astNodeWithData* 转换为astNode*,引用header 字段,并在预期的方式?
如果没有,有没有办法指示我的编译器(gcc,如果有帮助)强制执行这样的安排?
【问题讨论】:
-
“我可以将 astNodeWithData* 转换为 astNode* 的这种方式,”最好避免。寻找不涉及 cast 的解决方案。 (
struct/union的struct等) -
即使你使用 union 或 memcpy,也不要忘记打包结构
-
@chux-ReinstateMonica,为什么要避免这种情况?这不就是
struct sockaddr*之类的东西吗? -
struct sockaddr*用于 C 的受控子集(例如 *nix),而不是在 C 的广阔世界中。代码可以对第一个成员(如果是通用类型)使用强制转换技巧,但是除此之外,便携性被牺牲了,UB 隐约可见。施法技巧也击败了类型检查。 IMO,两者都没有必要。