-1

The following condition, during my tests, always returns True

var
  Tmp : Boolean;
begin
  if(Tmp)
  then ShowMessage('True')
  else ShowMessage('False');
end;

On compiling, I get the following warning message:

[DCC Warning] Unit1.pas(30): W1036 Variable 'Tmp' might not have been initialized

Does checking an unassigned local Boolean variable always returns True or is it pure casuality?

Fabrizio
  • 7,603
  • 6
  • 44
  • 104
  • 1
    You are far more likely to get TRUE than FALSE because any non-zero value will return TRUE. Also, the likelihood is that the same bit of memory will be used every time and that it will often have the same value every time. Neither, though, is guaranteed. – Dsm Sep 03 '19 at 14:58
  • @dsm - Note that it's the compilers discretion to generate what to test. In Delphi byte value of a boolean true is 1 not "not 0". Indeed `if tmp = true` will generate a test against 1 when optimizations are off, and the likelihood of having a 'false' message will be higher. – Sertac Akyuz Sep 03 '19 at 15:23
  • @SertacAkyuz Yes indeed and it is an often asked question why 'if x = TRUE' then does not necessarily behave like 'If x then'. But in this case the latter form was used. – Dsm Sep 03 '19 at 15:58
  • @dsm - The alternate form was an example. My point is that, it may not be safe to assume any non-zero value will be true, even in the mode as used in the question. Because the specification is not that. It's just how the current codegen implements the specs. – Sertac Akyuz Sep 03 '19 at 16:06
  • I didn't downvote, but I think I can guess why your Q was downvoted. The question "Are local boolean variables initialized?" is a special case of "Are local variables initialized?", which is a Q that has been asked many times. Googling "Delphi variables initialized" yields https://stackoverflow.com/questions/132725/are-delphi-variables-initialized-with-a-value-by-default as the first result. – Andreas Rejbrand Sep 04 '19 at 08:35

3 Answers3

5

In my test app

if (Tmp) then

compiles to

cmp byte ptr[ebp-$05],0
jz +$0c

so it is a simple test of whether the contents of the Tmp variable, which is on the stack, is zero.

The value at the tested stack location is determined by previouse use of the stack and so, from a statistical point of view, is much more likely not to be zero than zero. Hence your observation.

MartynA
  • 30,454
  • 4
  • 32
  • 73
  • Random isn't a great choice of word. It is pretty rare for a value on the stack to have a value that wasn't explicitly set by an earlier piece of code. – David Heffernan Sep 03 '19 at 16:12
  • @DavidHeffernan: Fair comment, but I could not think of a more concise way of putting it. – MartynA Sep 03 '19 at 16:24
  • Indeterminate is how I would say it – David Heffernan Sep 03 '19 at 16:33
  • @DavidHeffernan: but on any occasion the value has been set deterministically, and it, or rather its equality to zero, isn't indeterminate as soon as the `cmp` instruction executes - a point which may be lost on readers whose mother tongue isn't English. Anyway ... – MartynA Sep 03 '19 at 16:41
  • 1
    "from a statistical point of view, is much more likely not to be zero than zero" Are you sure? Most of the time I run code like this, I get `false`. Zeros bytes are pretty common in RAM. – Andreas Rejbrand Sep 04 '19 at 10:58
4

An uninitialised variable has an indeterminate value. It could be either true or false.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • This answer is a bit too concise: you should arguably clarify by stating that "an uninitialized *local and unmanaged* variable has an indeterminate value", like a local boolean or integer. Global variables and class fields are always initialized, as are local managed (reference-counted) variables, like strings and dynamic arrays. – Andreas Rejbrand Sep 04 '19 at 06:09
  • @Andreas Global variables are always initialized. Managed type variables are always initialized. Class fields are always initialized. – David Heffernan Sep 04 '19 at 06:32
  • Sorry, not my intension to sound harsh or anything. – Andreas Rejbrand Sep 04 '19 at 06:40
2

A boolean value is more or less a "Language wrapped" Byte. When it is uninitialized, it contains a "random" integer value. (It depends on whatever is on the stack when calling the method).

So your code is pretty much the same as

var
  Tmp : Byte;
begin
  if (Tmp = 0)
  then ShowMessage('True')
  else ShowMessage('False');
end;

Can an uninitialized byte be 0? Yup. Same goes for a boolean value, it can be False.

As a side note, the fact that boolean are implemented as an Integer value is exactly the reason why we don't test it against TRUE.

var
  b : Boolean;
begin
  B := Boolean(128);

  if B = True then //128 <> 1
    ShowMessage('This message won''t show'); 
  if B then
    ShowMessage('This message will show');
end;
Ken Bourassa
  • 6,363
  • 1
  • 19
  • 28
  • I have a legacy code that I think had this pattern. You rang alarms here. Thank you I think I need to fix some bugs before they get surfaced. Again Thank you. – Nasreddine Galfout Sep 04 '19 at 18:12