Is it ok to use a pointer which point to the address of a variable declared inside "if" statement ? Example as below:
...
int *pTest = 0;
if (...)
{
int x = 10;
pTest = &x;
}
else
{
int x = 100;
pTest = &x;
}
...
// use pTest
Is it ok to use a pointer which point to the address of a variable declared inside "if" statement ? Example as below:
...
int *pTest = 0;
if (...)
{
int x = 10;
pTest = &x;
}
else
{
int x = 100;
pTest = &x;
}
...
// use pTest
The problem is the life span of the pointer is greater than that of the object pointed to. This smells bad and you should rethink what you're trying to do.
The short answer is that it is not safe to use that pointer. The long answer is more complicated. You can do it if you do this in a very specific way, that honestly, I don't think you ever should. The pointer pTest will in all likeliness point to a position relative to the stack pointer. As long as nothing else clobbers that location, you are safe to use it. This is why it might "work" in certain situations. That said, here are some of the things that could cause that to fail:
Another variable might occupy the same space because once that variable is out of scope, another variable might take up the same space. This is similar to using memory that you have freed.
The compiler may do a transformation on your code making the assumption that it is not relying on undefined behavior (which this is). This could, for example, manifest that the compiler simply optimizes out this line:
pTest = &x;
The reason that the compiler may optimize out that particular line is that it concludes that any code that relies on reading that pointer from there on is relying on undefined behavior and so (ideally) the programmer knows this and wouldn't write code that depends on undefined behavior. The optimizer will then conclude that the most efficient solution is to nothing. That won't break any code that is not relying on undefined behavior.
UPDATE: I found this relevant question. Thanks to the standard citations in there, I can say that there is indeed a paragraph causing the pointer value to become invalid when the object's lifetime ends. In addition, performing an lvalue-to-rvalue conversion on a pointer with an invalid value is implementation-defined behaviour.
Thus, my below answer should ultimately be changed to implementation-defined. This means that your implementation is required to document what it will do when performing this lvalue-to-rvalue conversion, if that matters to you.
I believe this is okay by the standard if your definition of use means lvalue-to-rvalue conversion (e.g., printing the value, copying the value into another pointer, not dereferencing it¹).
[cov.lval]/3.3-3.4:
Otherwise, if the object to which the glvalue refers contains an invalid pointer value ([basic.stc.dynamic.deallocation], [basic.stc.dynamic.safety]), the behavior is implementation-defined.
Otherwise, the value contained in the object indicated by the glvalue is the prvalue result.
An implementation may have relaxed pointer safety, in which case the validity of a pointer value does not depend on whether it is a safely-derived pointer value. Alternatively, an implementation may have strict pointer safety, in which case a pointer value referring to an object with dynamic storage duration that is not a safely-derived pointer value is an invalid pointer value unless the referenced complete object has previously been declared reachable ([util.dynamic.safety]).
So if we have strict pointer safety, it's still valid - this piece doesn't make it invalid because it doesn't refer to an object with dynamic storage duration.
In short, I claim it's safe to use in the context of lvalue-to-rvalue conversions. If there is another paragraph in the standard making its value invalid because the referred-to object no longer exists, or some obscure trouble with "the value contained in the object indicated by the glvalue", I would love to see it.
¹: There's some great discussion in this general area here. I simplified this part since most uses of *p
would be undefined behaviour.
It would have been okay if you allocated memory to variable x using "new" and directed a pointer towards it . Because when the scope of variable x ends (as outside if) , the VALUE of x will still remain on heap (dynamic memory allocated to your program) and your pointer will still be pointing to some valid value . but in your case, since the memory allocated to variable x wasn't allocated dynamically, so once the scope of x ends outside its if's block, VALUE of x also wipes out and so in this case the pointer is now NOT pointing to variable's value, rather it is now pointing to some garbage value