I heard about compiler optimizations.
For example the one when:
while(myBool)
doStuff();
compiler knows you do not modify myBool inside a while loop, it just read myBool once and doesn’t check it every time.
This can be affected by volatile keyword right?
So I have tried to “trick” compiler, it thinks value was not changed.
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;
}
}
But even with full optimizations turned on (vs2012), this does not trick the compiler. This is probably very lame trick 🙂
How can I trick it? Is it even possible?
My goal is to create simple single-threaded program, which prints “test” with volatile keyword used and prints infinite-times “test” without the keyword.
EDIT: Unfortunately I am not good with assembler, so I really can not read if the memory reading was optimized out in the first place 🙂
What you’re doing is undefined behavior. You can’t access
s.bby writing to*((&s.a)+1)instead since there’s no guarantee thats.aands.bdon’t have any padding bytes between them.If you want to force there to be no padding, look into your compiler options. For GCC/Clang, you’d declare the structure with
__attribute__((packed)). For MSVC, you’d use the#pragma packdirective.There’s no good reason to be accessing
s.bthroughs.ausing that code. What you should really do in this case, assuming you have a good reason for not accessings.bdirectly, is use an array (volatile, if need be). Arrays are guaranteed to be contiguous in memory without needing special attributes/pragmas.Furthermore, the compiler won’t make certain optimizations in some cases: if
iis a variable and you write toa[i]followed by a read ofa[1], the compiler can’t assume thata[1]wasn’t just written to, so it won’t be able to cache it in a register. Whereas if you have two unrelated variablesaandband you write to*(&a+1)and then read fromb, the compiler will assume thatbwas not just written to. That’s one very good reason why*(&a+1)is undefined behavior, since it leads the compiler to make untrue assumptions and cause your program to behave in strange ways.