我正在寻找以下问题的答案:may_alias
是否适合作为指向某个类Foo
的对象的指针的属性?或者必须仅在课堂级别使用?
考虑以下代码(它基于更复杂的实际示例):
#include <iostream>
using namespace std;
#define alias_hack __attribute__((__may_alias__))
template <typename T>
class Foo
{
private:
/*alias_hack*/ char Data[sizeof (T)];
public:
/*alias_hack*/ T& GetT()
{
return *((/*alias_hack*/ T*)Data);
}
};
struct Bar
{
int Baz;
Bar(int baz)
: Baz(baz)
{}
} /*alias_hack*/; // <- uncommeting this line apparently solves the problem, but does so on class-level(rather than pointer-level)
// uncommenting previous alias_hack's doesn't help
int main()
{
Foo<Bar> foo;
foo.GetT().Baz = 42;
cout << foo.GetT().Baz << endl;
}
有没有办法告诉gcc单指针may_alias
是另一个?
考虑以下代码片段:
#include <iostream>
using namespace std;
int main()
{
long i = 42;
long* iptr = &i;
//(*(short*)&i) = 3; // with warning
//(*(short*)iptr) = 3; // without warning
cout << i << endl;
}
取消注释其中一行以查看编译器输出的差异。
答案 0 :(得分:2)
简单回答 - 对不起,没有。
__ attrbite__向编译器发出指令。对象存在于执行程序的存储器中。因此__attribute__列表中的任何内容都与运行时执行无关。
答案 1 :(得分:1)
Dimitar是正确的。 may_alias是类型属性。它只能应用于类型,而不适用于类型的实例。你想要的是gcc所谓的“变量属性”。对一个特定指针禁用优化并不容易。如果用这个指针调用一个函数,编译器会做什么?该函数可能已经编译并且将基于传递给函数的类型而不是基于指针中的地址存储(您应该看到为什么这是一个类型属性)
现在,根据您的代码,可能会起作用:
#define define_may_alias_type(X) class X ## _may alias : public X { } attribute ((may_alias));
当它可能是别名时,您只需将指针作为Foo_may_alias *
(而不是Foo *
)传递。但这很糟糕
关于警告的问题,这是因为-Wall
默认为-Wstrict-aliasing=3
,这不是100%准确。实际上,-Wstrict-aliasing
永远不会100%准确,但根据水平,你会得到或多或少的假阴性(和误报)。如果您将-Wstrict-aliasing=1
传递给gcc,则会看到两个警告