Recent

Author Topic: initialization of array of pointers  (Read 5265 times)

MarkMLl

  • Hero Member
  • *****
  • Posts: 6676
Re: initialization of array of pointers
« Reply #15 on: April 06, 2021, 06:15:15 pm »
The original code was

Code: Pascal  [Select][+][-]
  1.         {arr: ArrayOfPReal = (@x, @x); ok}
  2.         arr: ArrayOfPReal = (@x, px); {Illegal expression}
  3.  

Now it might be that somebody has moved the goalposts, but I read the failing expression as two pointers: nobody was trying to dereference anything.

However the bottom line is that an address that can't be resolved by the compiler and if necessary relocated by the linker can't be used as an initialiser.
Saying "dereference" is a poor choice of words on my part but, px is just a convenient/human name given to an offset.  To get the value _stored_ at that offset (which is what that arr declaration is trying to do) then px has to be dereferenced.  IOW, px is some offset, px^ is the value stored at that offset (in this case @x)

The OP wasn't trying to get "the value stored at" until runtime, and that wasn't where the problem was. I think the thread's tangled, possibly because of Jamie's contribution.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

440bx

  • Hero Member
  • *****
  • Posts: 3946
Re: initialization of array of pointers
« Reply #16 on: April 06, 2021, 06:26:27 pm »
The OP wasn't trying to get "the value stored at" until runtime, and that wasn't where the problem was. I think the thread's tangled, possibly because of Jamie's contribution.

MarkMLl
I'm under the (possibly mistaken) impression that he wanted to say @x by specifying px instead.  If that is correct then, the compiler has to look at what is _stored_ in px (effectively asking the compiler to dereference the offset px to obtain its value, which is @x)
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

MarkMLl

  • Hero Member
  • *****
  • Posts: 6676
Re: initialization of array of pointers
« Reply #17 on: April 06, 2021, 06:40:13 pm »
I'm under the (possibly mistaken) impression that he wanted to say @x by specifying px instead.  If that is correct then, the compiler has to look at what is _stored_ in px (effectively asking the compiler to dereference the offset px to obtain its value, which is @x)

The declaration was

Code: Pascal  [Select][+][-]
  1.     type
  2.         PReal = ^Real;
  3.         ArrayOfPReal = array[0..1] of PReal;
  4.      
  5.     var
  6.         x: Real = 3.2;
  7.         px: PReal = @x;
  8.  

Now I obviously note Sven's comment about what does and doesn't (and won't, and can't, so there.) work, but during initialisation px unambiguously resolves to @x without having to dereference anything. And the array is being initialised during compilation/linkage/loading, i.e. nothing has the option of changing the value of px before it's used.

I wonder what would have happened if instead of being a var it was a const?

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

lucamar

  • Hero Member
  • *****
  • Posts: 4219
Re: initialization of array of pointers
« Reply #18 on: April 06, 2021, 07:43:51 pm »
I wonder what would have happened if instead of being a var it was a const?

Exactly the same unless it was declared as an untyped const. As a typed const it would have the same constraints (in this regard) that an initialized var.
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.12/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

440bx

  • Hero Member
  • *****
  • Posts: 3946
Re: initialization of array of pointers
« Reply #19 on: April 06, 2021, 08:18:09 pm »
<snip> during initialisation px unambiguously resolves to @x without having to dereference anything.
Strictly speaking that is not correct.  px is the name of an offset in memory, the value held at that offset is obtained by dereferencing it.

Consider what happens with a_zero based_ array, for the sake of example named "MyArray".  In FPC (and in C) MyArray is an address (an offset in memory which is what a pointer is.)  Obtaining what is stored at MyArray[0], is done with (MyArray + 0)^ which is a dereference of MyArray, i.e, (MyArray + 0) = MyArray. 

Unlike with arrays, in the case of variables and when generating code, the compiler generates code that dereferences the variable's offset to obtain the variable's value and, unlike with arrays, requires the @ operator in order to get the offset.

Succinctly, whenever a value stored at an offset is obtained, de-referencing took place.  Without the de-reference, a variable's name identifies an offset, not the value stored at that offset.  What confuses people is that, in most cases, the de-referencing takes place automatically.  The compiler generates code that tells the CPU to get the _value_ stored at the variable's offset instead of just the offset (except if the variable is an array.)


(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

MarkMLl

  • Hero Member
  • *****
  • Posts: 6676
Re: initialization of array of pointers
« Reply #20 on: April 06, 2021, 08:42:08 pm »
As you say, px is a variable. But its content is known in exactly the same way as 1 + 1 is known during compilation without needing to be computed by run-time operations.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

440bx

  • Hero Member
  • *****
  • Posts: 3946
Re: initialization of array of pointers
« Reply #21 on: April 06, 2021, 09:02:01 pm »
As you say, px is a variable. But its content is known in exactly the same way as 1 + 1 is known during compilation without needing to be computed by run-time operations.
No, because the compiler doesn't try, nor should it try, to look at values stored in memory.  In the case of 1 + 1, the compiler knows it's 2 without having to inspect any memory location.

In the case of the OP's px, the compiler would have to look at _what_ is stored at the offset px, that it won't do that nor should it try.

Just because it is humanly obvious in the OP's case that the value in px is @x doesn't mean the compiler should use that knowledge.  The compiler won't and should not look at what is _stored_ at offset px.  The compiler can only concern itself with what is true and remains true at compile time _and_ runtime which is, the address/offsets of what is _declared_ (not calculated) in the program.
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

engkin

  • Hero Member
  • *****
  • Posts: 3112
Re: initialization of array of pointers
« Reply #22 on: April 06, 2021, 10:45:13 pm »
The problem is as follows, for the compiler to use the value assigned to px or any pointer for that matter, it has to dereference px at compile time.  dereferencing a pointer is a runtime operation, not a compile time one.

During compilation there is no pointer, and no memory address for it. At this time the compiler has a structure that describes this variable, its type, local or global, and its initial value if any. The compiler does not need to dereference any pointer, it just passes that same initial value to the structure that represents the array.

It's not confusing because in one case it's a constant (@x) and in the other it's a variable (px^). 

In run-time code, yes. @x is a constant, and px^ is a variable. In compile time within the initialization section, no, both are constants.

It isn't initialized with constants in both cases.  In the case of px, it is initialized with the value of a variable and no compiler is going to dereference the value of a pointer at compile time even if the value of the pointer happens to be known.

As I said above, no dereferencing is going to happen, nor needed at compile time. Just passing the value from one structure to the other one.

There are definitely some cases where it would be impossible, e.g, when the pointer isn't initialized.  At runtime, if a programmer dereferences a nil pointer, that causes an access violation.  To have a compiler dereference pointers at compile time, it would have to interpret the code as it is compiling because if pointer dereferencing is allowed at compile time then it has to support dereference chains where one pointer has the value of another which has the value of another and so on until it finds the "root pointer" that has (hopefully) been assigned a value.  That's a nightmare for a compiler (not to mention for the programmer who has to write that compiler.)

Again, no dereferencing is needed during compile time. Dereferencing is a run-time concept.

In addition to the above, there is a semantic problem in allowing an array element to be a variable.  The statement:
Code: Pascal  [Select][+][-]
  1. arr: ArrayOfPReal = (@x, px);
states that arr[1] is px, therefore whatever value px has at anytime should also be the value of arr[1].  IOW, at runtime when px is assigned a new value then arr[1] should have that same value since arr[1] is px.

That's the semantic meaning of that declaration. 

I don't think so, because this is not how you get this meaning in Pascal. Absolute is the keyword used to provide this meaning. It would be more along:
Code: Pascal  [Select][+][-]
  1. var
  2.   arr: array[0..1] of pinteger;
  3.   x: pinteger absolute arr[1];

440bx

  • Hero Member
  • *****
  • Posts: 3946
Re: initialization of array of pointers
« Reply #23 on: April 07, 2021, 12:19:09 am »
I'm going to try a different way of explaining this.  Look at this code :
Code: Pascal  [Select][+][-]
  1. program test;
  2. var
  3.   a  : integer = 1;
  4.   b  : integer = a;  
  5. begin
  6. end.
The compiler won't accept that.  The reason it won't accept it is because in order to initialize "b", it has to obtain whatever is _stored_ at the offset/variable a. 

Now consider this :
Code: Pascal  [Select][+][-]
  1. program test;
  2. const
  3.   a  = 1;
  4.   b  = a;  
  5.   c  = b;
  6.   d  = c;
  7. begin
  8. end.
it will accept that without complaint. 

The reason is, because in the first case, the compiler has to inspect what is _stored_ at the offset "a" "b" whereas in the second case, memory does _not_ need to be inspected to determine the values of b, c, and d.

if the compiler allowed the first case then, it would be completely reasonable for a programmer to expect the value of "b" to always be equal to the value of "a".  Updating two _different_ memory locations is the programmer's responsibility not the compiler's.  The compiler isn't going to touch that thing with a 10 foot poll.
« Last Edit: April 07, 2021, 12:48:33 am by 440bx »
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

engkin

  • Hero Member
  • *****
  • Posts: 3112
Re: initialization of array of pointers
« Reply #24 on: April 07, 2021, 01:37:00 am »
You are still thinking in run-time terms.

There are no memory locations allocated for these variables. The compiler is reading the source code and building a tree and symbol tables to later generate the assembly code.

It is during this time, and before the generation of assembly files or code, the compiler knows the initial values that would be given to all the variables.

To give b its initial value, the compiler has to find the variable a in its chain of variables and get its initial value from the structure (record or object) that represents this variable at this time -the compile time.

Notice both variables are not in memory, and there is no assembly code, yet.

440bx

  • Hero Member
  • *****
  • Posts: 3946
Re: initialization of array of pointers
« Reply #25 on: April 07, 2021, 02:41:19 am »
To give b its initial value, the compiler has to find the variable a in its chain of variables and get its initial value from the structure (record or object) that represents this variable at this time -the compile time.
Yes, it could do that in that specific case when "a" is initialized but, there is a semantic problem with that, specifically, it means that this code:
Code: Pascal  [Select][+][-]
  1. var
  2.   a : integer = 1;
  3.   b : integer = 1;

is the same as this code :
Code: Pascal  [Select][+][-]
  1. var
  2.   a : integer = 1;
  3.   b : integer = a;

I'll grant you that the compiler could rummage through its parse tables, get the value "a" has been initialized to and assign that to "b" but, as you've already pointed out in a past post, if "a" isn't initialized then there is a problem.   Even emitting an error in that case is questionable because a variable does not need to be initialized but the statement "b : integer = a;" gives the _impression_ that "b" is initialized when it wouldn't be if "a" wasn't.

Semantically, at least to me, "b : integer = a;" means that variable "b" is either an alias for variable "a" or somehow the compiler is going to generate code to ensure that the value stored in "b" always equals the value stored in "a" which is definitely not something any compiler would ever want to even try doing.

(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

engkin

  • Hero Member
  • *****
  • Posts: 3112
Re: initialization of array of pointers
« Reply #26 on: April 07, 2021, 03:26:43 am »
Semantically, at least to me, "b : integer = a;" means that variable "b" is either an alias for variable "a" or somehow the compiler is going to generate code to ensure that the value stored in "b" always equals the value stored in "a" which is definitely not something any compiler would ever want to even try doing.

You understood from "a : integer = 1;" that the initial value for " a " is going to be 1. Only the initial value, right? Similarly, "b : integer = a;" refers to the initial value. Also, "pa : pinteger = @a;" is dealing with the initial value.

As for the other meaning Pascal has the keyword Absolute as in
b : integer absolute a;

440bx

  • Hero Member
  • *****
  • Posts: 3946
Re: initialization of array of pointers
« Reply #27 on: April 07, 2021, 04:59:11 am »
You understood from "a : integer = 1;" that the initial value for " a " is going to be 1. Only the initial value, right?
Yes, because 1 is a constant and obviously constants don't change.  In the same vein, an address such as @x is also a constant.  No problem with those.

Similarly, "b : integer = a;" refers to the initial value.
Honestly, to me that declares that variable "b" is always equal to variable "a" which is problematic for a compiler to implement.

As for the other meaning Pascal has the keyword Absolute as in
b : integer absolute a;
I have no problem with the absolute statement.  It declares a different name for an already named offset usually to associate a different type with it.  The important thing is that absolute does _not_ allocate storage for the name it declares whereas the declaration "b : integer = a;" does.
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

engkin

  • Hero Member
  • *****
  • Posts: 3112
Re: initialization of array of pointers
« Reply #28 on: April 07, 2021, 05:53:56 am »
You understood from "a : integer = 1;" that the initial value for " a " is going to be 1. Only the initial value, right?
Yes, because 1 is a constant and obviously constants don't change.  In the same vein, an address such as @x is also a constant.  No problem with those.

While 1 is a constant "a" is not, and 1 was just its initial value.

Similarly, "b : integer = a;" refers to the initial value.
Honestly, to me that declares that variable "b" is always equal to variable "a" which is problematic for a compiler to implement.

Why "always", we are not declaring constants.

More over, this problematic meaning is not logical, because it does not add any benefit. Keeping two separate variables always identical has no value. Why would there be two separate storage locations in sync and of the same type? where would you use that?

On the other hand, having the same "initial" value for two or more variables is of practical use.

As for the other meaning Pascal has the keyword Absolute as in
b : integer absolute a;
I have no problem with the absolute statement.  It declares a different name for an already named offset usually to associate a different type with it.  The important thing is that absolute does _not_ allocate storage for the name it declares whereas the declaration "b : integer = a;" does.

For us in this thread "absolute" is to clear the confusion we had earlier that "b : integer = a;" has a different meaning than "b : integer absolute a;"

MarkMLl

  • Hero Member
  • *****
  • Posts: 6676
Re: initialization of array of pointers
« Reply #29 on: April 07, 2021, 08:50:48 am »
While 1 is a constant "a" is not, and 1 was just its initial value.

What's more a could /potentially/ be removed by optimisation if it weren't used at runtime, since the only important thing is that the compile-time parse tree which gives it its value is propagated.

In any event, nothing's going to change and at least we've got a robust error message indicating that the compiler's unhappy about what it's asked to do.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

 

TinyPortal © 2005-2018