If the value of an uninitialized variable shouldn't affect the value of an expression, is it still UB?

这一生的挚爱 提交于 2019-12-23 07:49:44

问题


This is a follow-on from a discussion, which I think deserves a question of its own.

Basically, is the result of this undefined?

int x;
int y = 1 || x;

There are two "common-sense" arguments here:

  1. Mathematically speaking, no matter what the value of x, the value of y should be 1.
  2. Because of short-circuiting, x is never evaluated anyway.

But the counterargument is that we have an expression that involves an uninitialized variable, so all bets are off (in theory).

More generally, if the value of an uninitialized variable can't possibly affect the result of an expression, is it "safe"? e.g.:

int x;
int y = x - x;

Usual disclaimer: Of course, I'm not advocating ever writing code like this.


回答1:


In C, it is undefined behavior to use the value of an object with automatic storage duration while it is indeterminate. (J.2, informative) but it's OK for variables with automatic storage duration to hold an indeterminate value.

An expression can only have its value used if it is evaluated and according to 6.5.12 (Logical OR operator) the second operand is not evaluated (let alone have its value used) if the first operand compares unequal to 0.




回答2:


Disclaimer: I thought the question was for C++ as well. Apparently it is for C only. I don't speak C-standardese, but I believe my answer holds true for C as well, although using different termiology

int x;
int y = 1 || x;

is well defined because x is simply not evaluated - guarantee of short-circuit evaluation of ||.

int x;
int y = x - x;

invokes undefined behvior, because x is evaluated and an lvalue-to-rvalue conversion takes place. If that conversion didn't take place, the behavior would be well-defined, for example:

int x;
int* y = &x;
int z = &x - &x;

Here x is also evaluated but no lvalue-to-rvalue conversion takes place, so it's defined.




回答3:


Regarding y = x - x;, one worst-case scenario to bear in mind is that an uninitialized variable might contain a trap value.

You can't rely on the presence of an optimizer to realise that x - x doesn't actually depend on the value of x, and so certainly the implementation is allowed to use the value of x in evaluating x - x, and it's used in the abstract machine.

So if it's a trap value, you'd have a hardware error or whatever the implementation does when it traps. UB, anyway.

I remember that one system I used added extra guarantees about the behavior of indeterminate values. It stated that using an indeterminate value would not explode, but also was not required to behave as if the value was any actual value of the type. So, x-x would result in another indeterminate value, not necessarily 0. This is actually less useful than trapping, since it stores up the programming error for later use when you least expect it, but AFAIK it's completely conforming since behaviour is not defined by the standard.




回答4:


Basically, is the result of this undefined?

int x; int y = 1 || x;

Nopes! x is never used/ evaluated.

int y = x - x; invokes UB.



来源:https://stackoverflow.com/questions/7269545/if-the-value-of-an-uninitialized-variable-shouldnt-affect-the-value-of-an-expre

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!