Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/155.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何欺骗编译器优化内存读取?_C++_Compiler Construction - Fatal编程技术网

C++ 如何欺骗编译器优化内存读取?

C++ 如何欺骗编译器优化内存读取?,c++,compiler-construction,C++,Compiler Construction,我听说了编译器优化 例如: while(myBool) doStuff(); 编译器知道您不会在while循环中修改myBool,它只读取myBool一次,不会每次都检查它 这可能会受到volatile关键字的影响,对吗 所以我试图“欺骗”编译器,它认为值并没有改变 int main() { struct st { int a; int b; //I want to make difference by writing volatile

我听说了编译器优化

例如:

while(myBool)
    doStuff();
编译器知道您不会在while循环中修改myBool,它只读取myBool一次,不会每次都检查它

这可能会受到
volatile
关键字的影响,对吗

所以我试图“欺骗”编译器,它认为值并没有改变

int main()
{
    struct st 
    {
        int a;
        int b; //I want to make difference by writing volatile here
    }s;

    s.b = 1;

    while(s.b > 0)
    {
        *((&s.a)+1) = 0;
        std::cout << "test" << std::endl;
    }
}
intmain()
{
结构街
{
INTA;
int b;//我想通过在这里写volatile来改变
}s;
s、 b=1;
而(s.b>0)
{
*(&s.a)+1)=0;

std::cout我想您是在问如何确保编译器假定值几乎相同(在您的示例中为true),以便编译器针对该值进行优化。 如果您这样做了,那么您的应用程序正在寻找一组特定于编译器的关键字。 这是我在g中使用的++

#define predict_true__(exp)     __builtin_expect((exp), 1)
#define predict_true__(exp)       (exp)
你可以这样做

while ( predict_true__( myBool ))
    doStuff() ;
它将高效运行,因为myBool是真的。 希望它能帮助你,你会知道在你使用视觉效果的情况下应该看什么


另外:我发现下面的帖子谈到了这一点。不过,我恐怕这是一个悲伤的话题:

你所做的是未定义的行为。你不能通过写
*(&s.a)+1来访问
s.b
相反,因为不能保证
s.a
s.b
之间没有任何填充字节

如果您想强制不使用填充,请查看您的编译器选项。对于GCC/Clang,您可以使用声明结构。对于MSVC,您可以使用

没有充分的理由通过
s.a
使用该代码访问
s.b
。在这种情况下,假设您有充分的理由不直接访问
s.b
,您真正应该做的是使用数组(
volatile
,如果需要的话).保证数组在内存中是连续的,而不需要特殊属性/杂注


此外,编译器在某些情况下不会进行某些优化:如果
i
是一个变量,并且您先写入
a[i]
,然后读取
a[1]
,编译器就不能假定
a[1]
不仅仅是写入的,因此它无法将其缓存在寄存器中。然而,如果您有两个不相关的变量
a
b
,并且您写入
*(&a+1)
,然后从
b
读取,编译器将假定
b
不仅仅是写入的。这就是
*(&a+1)的一个很好的原因
是未定义的行为,因为它会导致编译器做出不真实的假设,并导致程序以奇怪的方式运行。

简而言之,
结构在内存中不保证是连续的。数组是连续的。你不能这样访问结构


一个可能会有帮助的SO问题:。它会更详细地说明为什么不能这样做以及为什么不能这样做。但总结是,结构的字段之间可能有填充,也可能没有填充。我特别喜欢Charlie在这个问题上的回答。

试图摆脱每次迭代都对int和0进行一次比较的做法听起来像过早的优化。这实际上可以节省多少时间?关键是他想欺骗编译器在不应该的时候进行优化。他不是在试图节省时间。这不是java。你不必欺骗编译器进行优化。我不确定我是否理解这个问题。你想让编译器进行优化吗(在本例中,不重新读取变量)它应该在什么时候出现?这与说您想在编译器中找到错误不一样吗?@GManNickG:不一定是编译器错误。调用未定义的行为也可以工作,而不是编译器错误。这只会更改(静态)分支预测,不改变应用程序的行为(引入错误)如果
myBool
实际上不是
true
。对于具有良好分支预测的处理器,它甚至不会对任何经常调用的分支产生性能差异,从而matter@chris:谢谢你指出这一点。这就是我们在办公室使用的。我会把信息传递给这里的人,让他们改变来预测真实的,再次感谢!