小编L.C*_*.C.的帖子

在实践中,工会,别名和打字:什么有效,有什么不可行?

我有一个问题,了解使用GCC的工会可以做什么和不可以做什么.我阅读了有关它的问题(特别是这里这里),但他们关注C++标准,我觉得C++标准和实践(常用的编译器)之间存在不匹配.

特别是,我最近在阅读有关编译标志-fstrict-aliasingGCC在线文档中发现了令人困惑的信息.它说:

-fstrict走样

允许编译器采用适用于正在编译的语言的最严格的别名规则.对于C(和C++),这将根据表达式的类型激活优化.特别地,假设一种类型的对象永远不会与不同类型的对象驻留在相同的地址,除非类型几乎相同.例如,a unsigned intcan可以是a int,但不是a void*或a double.字符类型可以别名为任何其他类型.特别注意这样的代码:

union a_union {
  int i;
  double d;
};

int f() {
  union a_union t;
  t.d = 3.0;
  return t.i;
}
Run Code Online (Sandbox Code Playgroud)

从不同的工会成员阅读的做法比最近写的那个(称为"打字式")很常见.即使使用-fstrict-aliasing,只要通过union类型访问内存,就允许类型为punning.因此,上面的代码按预期工作.

这是我认为我从这个例子和我的疑虑中理解的:

1)别名仅适用于相似类型或char

1)的后果:别名 - 正如文字暗示的那样 - 是你有一个值和两个成员来访问它(即相同的字节);

怀疑:当它们具有相同的字节大小时,两种类型是相似的吗?如果没有,什么是类似的类型?

1)对于非相似类型(无论这意味着什么)的后果,别名不起作用;

2)类型双关语是指我们读的不同于我们写的成员; 它是常见的,只要通过union类型访问内存,它就可以正常工作;

怀疑:在类型相似的特定情况下别名是什么类型?

我感到困惑,因为它表示unsigned int和double不相似,所以别名不起作用; 然后在示例中它是int和double之间的别名,它清楚地表明它按预期工作,但称之为类型 - 惩罚:不是因为类型是或不相似,而是因为它是从一个不写的成员读取.但是从一个没有写的成员那里读取的是我所理解的混淆(正如这个词所暗示的那样).我迷路了.

问题: 有人可以澄清别名和类型惩罚之间的区别,这两种技术的用途是如何在GCC中发挥作用的?编译器标志有什么作用?

c++ gcc strict-aliasing

16
推荐指数
2
解决办法
1374
查看次数

标签 统计

c++ ×1

gcc ×1

strict-aliasing ×1