将结构别名为其第一个成员是否严格违反别名? [英] Is it a strict aliasing violation to alias a struct as its first member?

查看:67
本文介绍了将结构别名为其第一个成员是否严格违反别名?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

示例代码:

struct S { int x; };

int func()
{
     S s{2};
     return (int &)s;    // Equivalent to *reinterpret_cast<int *>(&s)
}

我认为这很普遍并且被认为可以接受.该标准确实确保该结构中没有初始填充.但是,这种情况未在严格的别名规则(C ++ 17 [basic.lval]/11)中列出:

I believe this is common and considered acceptable. The standard does guarantee that there is no initial padding in the struct. However this case is not listed in the strict aliasing rule (C++17 [basic.lval]/11):

如果程序尝试通过以下类型之一以外的glvalue访问对象的存储值,则行为未定义:

If a program attempts to access the stored value of an object through a glvalue of other than one of the following types the behavior is undefined:

  • (11.1)对象的动态类型,
  • (11.2)对象动态类型的cv限定版本,
  • (11.3)一种类似于对象的动态类型的类型(定义见7.5)
  • (11.4)一种类型,它是与对象的动态类型相对应的有符号或无符号类型,
  • (11.5)一种类型,它是与对象的动态类型的cv限定版本相对应的有符号或无符号类型,
  • (11.6)聚合或联合类型,其元素或非静态数据成员(包括递归地包括子聚合或所包含的联合的元素或非静态数据成员)中包括上述类型之一, li>
  • (11.7)一种类型,它是对象的动态类型的(可能是cv限定的)基类类型,
  • (11.8)char,unsigned char或std :: byte类型.
  • (11.1) the dynamic type of the object,
  • (11.2) a cv-qualified version of the dynamic type of the object,
  • (11.3) a type similar (as defined in 7.5) to the dynamic type of the object,
  • (11.4) a type that is the signed or unsigned type corresponding to the dynamic type of the object,
  • (11.5) a type that is the signed or unsigned type corresponding to a cv-qualified version of the dynamic type of the object,
  • (11.6) an aggregate or union type that includes one of the aforementioned types among its elements or non-static data members (including, recursively, an element or non-static data member of a subaggregate or contained union),
  • (11.7) a type that is a (possibly cv-qualified) base class type of the dynamic type of the object,
  • (11.8) a char, unsigned char, or std::byte type.

很明显,对象s正在访问其存储的值.

It seems clear that the object s is having its stored value accessed.

项目符号中列出的类型是进行访问的glvalue的类型,而不是被访问的对象的类型.在此代码中,glvalue类型为int,它不是聚合类型或联合类型,排除了11.6.

The types listed in the bullet points are the type of the glvalue doing the access, not the type of the object being accessed. In this code the glvalue type is int which is not an aggregate or union type, ruling out 11.6.

我的问题是:这段代码正确吗?如果是,那么在上面的哪些要点是允许的?

My question is: Is this code correct, and if so, under which of the above bullet points is it allowed?

推荐答案

强制转换的行为归结为[expr.static.cast]/13;

The behaviour of the cast comes down to [expr.static.cast]/13;

可以将指向 cv1 void的指针"类型的prvalue转换为指向 cv2 T的指针"的prvalue,其中T是对象类型,并且 cv2 cv1 具有相同的cv限定,或具有更高的cv限定.如果原来 指针值表示内存中字节的地址A,而A不满足T的对齐要求,则未指定结果指针值. 否则,如果原始指针值指向对象a,并且存在类型为T(忽略cv限定)的对象b,且 pointer-interconvertible 具有a,结果是指向b的指针.否则,转换后指针的值不变.

A prvalue of type "pointer to cv1 void" can be converted to a prvalue of type "pointer to cv2 T", where T is an object type and cv2 is the same cv-qualification as, or greater cv-qualification than, cv1. If the original pointer value represents the address A of a byte in memory and A does not satisfy the alignment requirement of T , then the resulting pointer value is unspecified. Otherwise, if the original pointer value points to an object a, and there is an object b of type T (ignoring cv-qualification) that is pointer-interconvertible with a, the result is a pointer to b. Otherwise, the pointer value is unchanged by the conversion.

pointer-interconvertible 的定义是:

The definition of pointer-interconvertible is:

如果满足以下条件,则两个对象a和b是指针可互换的:

Two objects a and b are pointer-interconvertible if:

  • 它们是同一个对象,或者
  • 一个是联合对象,另一个是该对象的非静态数据成员,或者
  • 一个是标准布局类对象,另一个是该对象的第一个非静态数据成员,或者,如果该对象没有非静态数据成员,则是该对象的第一个基类子对象,或者
  • 存在一个对象c,使得a和c是指针可互换的,而c和b是指针可互换的.
  • they are the same object, or
  • one is a union object and the other is a non-static data member of that object, or
  • one is a standard-layout class object and the other is the first non-static data member of that object, or, if the object has no non-static data members, the first base class subobject of that object, or
  • there exists an object c such that a and c are pointer-interconvertible, and c and b are pointer-interconvertible.

因此,在原始代码中,ss.x pointer-interconvertible 的指针,因此(int &)s实际上指定了s.x.

So in the original code, s and s.x are pointer-interconvertible and it follows that (int &)s actually designates s.x.

因此,在严格的别名规则中,正在访问其存储值的对象是s.x而不是s,因此没有问题,代码是正确的.

So, in the strict aliasing rule, the object whose stored value is being accessed is s.x and not s and so there is no problem, the code is correct.

这篇关于将结构别名为其第一个成员是否严格违反别名?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆