违反严格混叠,即使没有任何铸造? [英] Violating strict-aliasing, even without any casting?
问题描述
我想我真的问:是别名传递?如果编译器知道A可能是B的别名,而B可能是C的别名,那么它应该记住A可能因此别名为C.也许这个明显的传递逻辑不是必需的?
这是一个例子,为了清楚起见。对我来说最有趣的例子是严格别名问题:
// g ++ -fstrict-aliasing -std = c ++ 11 -O2
#include< iostream>
union
{
int i;
short s;
} u;
int * i =& u.i;
int main()
{
u.i = 1; // line 1
* i + = 1; // line 2
short& s = u.s;
s + = 100; // line 3
std :: cout
<< * i \t< * i < std :: endl // prints 2
<< u.i\t< ui < std :: endl // prints 101
;
return 0;
}
g ++ 5.3.0,在x86_64(但不是clang 3.5.0)上面的输出,其中 * i
和 ui
给出不同的数字。但它们应该给出完全相同的数字,因为 i
定义在 int * i =& ui;
code> i 不会改变。
我有一个理论:当'预测' 这个理论看起来是否合理? ui
,编译器会询问哪些行可能会影响 ui
的内容。其中包括第1行。和第2行,因为 int *
可以将联合成员的 int
别名。和第3行,因为任何可以影响一个联合成员( u.s
)可以影响同一个联合的另一个成员。但是当预测 * i
时没有意识到第3行可以影响 int
左值
从C ++的非活动成员中读取在C ++中是未定义的。 (在C99和C11中是合法的)。
因此,总而言之,编译器不需要假设/记住任何东西。
标准:
N4140§9.5[class.union] / 1
联合,非静态数据成员中的至多一个可以在任何时间是活动的,即,最多一个非静态数据成员的值可以随时存储在联合中。
I think I'm really asking: is aliasing "transitive"? If the compiler knows that A might alias B, and B might alias C, then surely it should remember that A might therefore alias C. Perhaps this "obvious" transitive logic isn't required however?
An example, for clarity. The most interesting example, to me, of a strict-aliasing issue:
// g++ -fstrict-aliasing -std=c++11 -O2
#include <iostream>
union
{
int i;
short s;
} u;
int * i = &u.i;
int main()
{
u.i = 1; // line 1
*i += 1; // line 2
short & s = u.s;
s += 100; // line 3
std::cout
<< " *i\t" << *i << std::endl // prints 2
<< "u.i\t" << u.i << std::endl // prints 101
;
return 0;
}
g++ 5.3.0, on x86_64 (but not clang 3.5.0) gives the above output, where *i
and u.i
give different numbers. But they should give exactly the same number, because i
is defined at int * i = &u.i;
and i
doesn't change.
I have a theory: When 'predicting' the value of u.i
, the compiler asks which lines might affect the contents of u.i
. That includes line 1 obviously. And line 2 because int*
can alias an int
member of a union. And line 3 also, because anything that can affect one union member (u.s
) can affect another member of the same union. But when predicting *i
it doesn't realise that line 3 can affect the int
lvalue at *i
.
Does this theory seem reasonable?
I find this example funny because I don't have any casting in it. I managed to break strict-aliasing with doing any casting.
Reading from inactive member of a union is undefined in C++. (It's legit in C99 and C11).
So, all in all, the compiler isn't required to assume/remember anything.
Standardese:
N4140 §9.5[class.union]/1In a union, at most one of the non-static data members can be active at any time, that is, the value of at most one of the non-static data members can be stored in a union at any time.
这篇关于违反严格混叠,即使没有任何铸造?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!