结构别名可以自己的首字母和唯一的成员吗?[英] Can a struct alias its own initial and only member?

本文是小编为大家收集整理的关于结构别名可以自己的首字母和唯一的成员吗?的处理方法,想解了结构别名可以自己的首字母和唯一的成员吗?的问题怎么解决?结构别名可以自己的首字母和唯一的成员吗?问题的解决办法?那么可以参考本文帮助大家快速定位并解决问题。

问题描述

例如,此代码是否有效,还是通过违反混叠规则来调用不确定的行为?

int x;
struct s { int i; } y;
x = 1;
y = *(struct s *)&x;
printf("%d\n", y.i);

我的兴趣是使用基于此的技术来开发一种用于执行别名读取的便携式方法.

更新:这是预期的用法情况,有点不同,但是当且仅当上述有效时,它才能有效:

static inline uint32_t read32(const unsigned char *p)
{
    struct a { char r[4]; };
    union b { struct a r; uint32_t x; } tmp;
    tmp.r = *(struct a *)p;
    return tmp.x;
}

gcc,根据需要,将其编译为一个32位负载,并且似乎避免了如果p实际上指向char以外的其他类型,可能会发生的混叠问题.换句话说,它似乎是GNU C __attribute__((__may_alias__))属性的便携式替代品.但是我不确定它是否真的很明确...

推荐答案

我相信这仍然会违反有效的打字规则.您需要访问未明确声明的内存位置(或通过存储在动态分配的情况下)通过该类型的表达式包含A struct a.

其他答案中没有引用的部分都不能用于逃避此基本限制.

但是,我相信您的问题有一个解决方案:使用__builtin_memcpy(),即使在独立环境中也可以使用(请参阅 -fno-builtin ).


请注意,该问题比我听起来不明确. C11第6.5节第7节告诉我们,可以通过具有的LVALUE表达式访问对象,该表达式具有的汇总或联合类型,其中包括其成员之间的一种类型之一..

C99的理由明确指出,这种限制是有指向骨料的指针和指向其成员之一的指针.

我相信在第一个示例的方式使用此漏洞的能力(但是不是,假设p没有指向实际的char [4])是意外后果,标准仅由于不精确的措辞而无法禁止.

还要注意,如果第一个示例有效,我们基本上可以潜入结构性键入,将其键入原本名义上打字的语言.除了常见的初始子序列(甚至那时,成员名称确实很重要)的结构中,相同的内存布局不足以使类型兼容.我相信这里也适用同样的原因.

其他推荐答案

我对混叠规则(C99,6.5p7)的读物的存在:

"在其中包含上述类型之一的汇总或联合类型 成员(包括,递归,是亚群落或包含工会的成员)或"

导致我认为这不会违反c的混叠规则.

但事实并不违反混叠规则不足以使该代码段有效.由于其他原因,它可能调用不确定的行为.

(struct s *) &x

不能保证指向有效的struct s对象.即使我们假设x的对齐方式适用于类型struct的对象,铸件之后的结果指针可能不会指向足够大的空间以容纳结构对象成员).

编辑:答案已从其初始版本

完全重新设计

其他推荐答案

不确定这是一个正确的答案,但是(在您的第二个示例中)可能发生的是:

  1. 编译器将struct a定义为一个8字节对象,在数组中的4个字节之后使用填充物(为什么?因为它可以).
  2. 然后,您使用tmp.r = *(struct a *)p;将p视为struct a的地址(即8个字节对象).它试图将此对象的内容复制到tmp.r中,也就是说,p所保留的地址的8个字节.但是您只允许从那里阅读4个字节.

实现不必复制填充字节,但允许它们这样做.

本文地址:https://www.itbaoku.cn/post/358968.html