为什么union*和struct*会有区别?

5
C标准规定,所有指向union的指针具有相同的表示和对齐要求。它还规定了所有指向结构体的指针也是如此。因此我的问题是:为什么标准没有规定指向union的指针具有与指向结构体的指针相同的表示和对齐要求?(我非常希望看到一个利用这一点的实现示例)。或者我是否错过了相关的文本?来自草案标准n1570(C11最终草案)的相关引用如下:“6.2.5类型 § 28”中提到,“指向void的指针应具有与指向字符类型的指针相同的表示和对齐要求。48)同样,对于兼容类型的限定或未限定版本的指针,其表示和对齐要求应相同。所有指向结构体类型的指针应具有彼此相同的表示和对齐要求。所有指向联合类型的指针也应具有彼此相同的表示和对齐要求。其他类型的指针不需要具有相同的表示或对齐要求。”

难道不是同样的原因,你不能强制要求指向 int 的指针具有与指向 char 的指针相同的表示和对齐要求吗? - CMPS
2
@Amir:这个问题还有更多需要考虑的地方。请看我的回答。 - Keith Thompson
顺便说一下:会给这个问题一些时间,或许会有人提出一个非常奇怪的实现方式,或是某些被遗忘已久的委员会讨论,或其他同样启发人心/令人惊讶的东西。 - Deduplicator
@Deduplicator:当涉及到C89时,委员会甚至没有明确提到它(“所有指向结构/联合类型的指针”)作为要求。这个“补充”的原因被认为是指向不完整类型的指针来自不同的翻译单元。在我最新的问题中,我已经分享了很多与此要求相关的信息。 - Dror K.
2个回答

5

无论是1989 ANSI C Rationale还是ISO C99 Rationale都没有讨论过这个问题。

我怀疑缺少这种要求的原因并不充分。可能委员会不想强制施加不必要的严格要求。我也怀疑在现实世界中是否存在指向结构体和指向联合体的指针具有不同表示方式的实现。

例如,考虑到结构体可以包含单个联合体成员,反之亦然,因此实现使用不同的表示方式可能没有好的理由,标准也没有理由要求所有实现使用相同的表示方式。

所有结构体指针“看起来都很像”的原因是为了允许使用不完整类型的指针。例如:

struct foo;

void func(struct foo *param);

struct foo { /* member declarations */ };

编译器只需要知道struct foo是一个struct类型,就可以生成对func()的调用,与此相同,不完整的联合类型也是如此。但是不完整的结构体类型无法作为联合体完成,反之亦然,因此假设它们具有相同表示的好处不大。

如果像你所说的那样,使用不同的结构和联合指针表示+对齐要求没有可能获得任何收益,那么强制规定它们没有区别有一个优点:更强的保证程序员,这可能使他能够确信在更广泛的变化范围内,他的程序是严格符合标准的,因此高度可移植。(即使有解决方法,直接和明确也更好...) - Deduplicator
1
@Deduplicator:委员会必须考虑到可能存在使用不同表示法的原因,而他们没有想到。标准中的每个要求都对所有实现者具有潜在的非零成本。强制要求联合和结构指针使用相同的表示法的优势并不那么显著。 - Keith Thompson
@Deduplicator: 如果委员会遵循你所描述的逻辑,我们熟知的 C 将不复存在。程序员已经拥有了最强的保证:结构体指针不需要与联合体指针相同。你所要求的并不是一个保证,而是一个狭隘的定义,这是不同的事情。严格遵守和可移植性,是关于遵循规则的。你所提议的是通过应用狭窄定义来改变规则,这绝对不是 C 的方式。 - Dror K.
编译器是否允许对“结构体”强制执行任意的最小对齐方式,以使此类指针在字寻址机器上更加高效?这将导致“结构体”和“联合体”指针之间存在显著差异。 - Deduplicator

0

尽管标准不要求实现这样做,但实施者可能会认识到具有指向多种需要不同对齐要求的类型的指针类型(例如 uint8_tuint16_tuint32_tuint64_t)的有用性,但仅需要遵守实际使用的访问类型的对齐要求(例如,仅在访问 uint16_t 时需要 16 位对齐)。使用联合类型的指针来访问实际上不是联合类型的对象可能看起来很奇怪,但 C 不提供其他语法来表明指针可以用于别名特定特定类型的东西,除了实际用于访问的类型。

如果系统使用单元地址,那么说所有结构体都将填充为整数个单元,并且必须对齐到单元边界,但对联合体强制执行这样的要求将使其无法用于上述目的。在这样的系统上,即使联合指针比结构体指针更大,也可能出现允许指向联合体的指针识别单个字节边界位置的情况(当直接访问仅对齐要求是令人满意的东西时),而结构体的指针仍然限制在单元边界上。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接