[编辑:这是动机:将变量的指针传递给外部函数可能会意外地破坏对“相邻”变量的一些优化,因为有可能获得指向由外部函数从原始指针计算的相邻变量的指针。以下为原帖,volatile
是为了模拟当前编译单元无法访问的外部函数,例如虚函数调用、闭源库函数等]
我想知道return t.a;
以下代码中的是否会优化为return 0;
.
//revision 1
struct T
{
int a;
int b;
};
void f_(int * p)
{
*p = 1;
}
auto volatile f = f_;
int main()
{
T t;
t.a = 0;
t.b = 0;
for (int i = 0; i < 20; ++i)
{
f(&t.b);
}
return t.a;
}
好吧,它不是。很公平,因为函数中的代码f
可以offsetof
用来获取指向t
然后 change的指针t.a
。所以优化off的负载是不安全的t.a
。
[编辑:再想一想,offsetof
这里还不够。我们需要container_of
,似乎没有办法在标准 C++ 中实现。]
但offsetof
不能用于非标准布局类型。所以我尝试了以下代码:
//revision 2
#include <type_traits>
struct T
{
private:
char dummy = 0;
public:
int a;
int b;
};
static_assert(!std::is_standard_layout_v<T>);
void f_(int * p)
{
*p = 1;
}
auto volatile f = f_;
int main()
{
T t;
t.a = 0;
t.b = 0;
for (int i = 0; i < 20; ++i)
{
f(&t.b);
}
return t.a;
}
不幸的是,它仍然无法正常工作。
我的问题是:
t.a
在上述情况下优化 away 的负载是否安全(修订版 2)- 如果不是,是否存在一些安排/建议使其成为可能?(例如,制作
T
更特殊的类型,或为成员b
in制作一些属性说明符T
)
PS 下面的代码针对 进行了优化return t.a;
,但是生成的循环代码效率有点低。而且,临时变量杂耍很麻烦。
//revision 3
struct T
{
int a;
int b;
};
void f_(int * p)
{
*p = 1;
}
auto volatile f = f_;
int main()
{
T t;
t.a = 0;
t.b = 0;
for (int i = 0; i < 20; ++i)
{
int b = t.b;
f(&b);
t.b = b;
}
return t.a;
}