Recent

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

clerfayt

  • Newbie
  • Posts: 5
initialization of array of pointers
« on: April 04, 2021, 10:16:41 pm »
Hi, i'm a pascal newbie and struggling with an init of an array of pointers.  %)
When using the address of a real variable directly it works, when using a pointer type variable the compiler says 'illegal expression'.
Could please someone help me and tell me what i'm doing wrong here?
Thx!
 
Code: Pascal  [Select][+][-]
  1. program test;
  2.     type
  3.         PReal = ^Real;
  4.         ArrayOfPReal = array[0..1] of PReal;
  5.      
  6.     var
  7.         x: Real = 3.2;
  8.         px: PReal = @x;
  9.         {arr: ArrayOfPReal = (@x, @x); ok}
  10.         arr: ArrayOfPReal = (@x, px); {Illegal expression}
  11.      
  12. begin
  13.     writeln((arr[1])^);
  14. end.
  15.  

MarkMLl

  • Hero Member
  • *****
  • Posts: 6686
Re: initialization of array of pointers
« Reply #1 on: April 04, 2021, 10:52:40 pm »
On which line is the error? My guess is that it's telling you that @x can't be used as an initialiser since it can't be resolved to a constant at compilation time.

Boilerplate: please cut-and-paste exact error messages and tell us what compiler version and OS you're using.

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: 4029
Re: initialization of array of pointers
« Reply #2 on: April 05, 2021, 12:39:19 am »
Could please someone help me and tell me what i'm doing wrong here?
There are a few things wrong with that code. 

Whenever you are writing a console application make sure you specify {$APPTYPE CONSOLE} if you don't, a writeln will cause an I/O error because the compiler will assume it's a GUI program.

The reason "arr: ArrayOfPReal = (@x, px); {Illegal expression}" is an illegal expression is because px is a _variable_ and the compiler cannot know the value held in px at compile time.  However, the compiler can and does know the _address_ it has assigned to x (and px but not their values).  Therefore asking for the address is fine but, asking for the value (which is what writing px does) of the variable isn't because the compiler cannot know that at compile time. 

If you have a hard time understanding that, think of it this way, say the program starts with a value of px = 3.5 and later during execution it changes to 9,  should the 2nd element of the array change every time px changes ?  The answer is "no" because the second element of the array is a different block of memory than the one identified by the name "px".  IOW, px does _not_ identify the second element of the array, it identifies a different area in memory.

HTH.
(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 #3 on: April 05, 2021, 03:48:21 am »
The reason "arr: ArrayOfPReal = (@x, px); {Illegal expression}" is an illegal expression is because px is a _variable_ and the compiler cannot know the value held in px at compile time.

I just did a quick test. Unless I made a mistake, the compiler *does* know the value px has at compile time. I saw the value using -al. I think the compiler is being lazy and does not want to use the value. Or more accurately, the compiler was not taught how to do that, yet.

engkin

  • Hero Member
  • *****
  • Posts: 3112
Re: initialization of array of pointers
« Reply #4 on: April 05, 2021, 03:54:20 am »
@jamie, I don't know what you're trying to do, but that code is not right.

440bx

  • Hero Member
  • *****
  • Posts: 4029
Re: initialization of array of pointers
« Reply #5 on: April 05, 2021, 06:57:16 am »
The reason "arr: ArrayOfPReal = (@x, px); {Illegal expression}" is an illegal expression is because px is a _variable_ and the compiler cannot know the value held in px at compile time.

I just did a quick test. Unless I made a mistake, the compiler *does* know the value px has at compile time. I saw the value using -al. I think the compiler is being lazy and does not want to use the value. Or more accurately, the compiler was not taught how to do that, yet.
You didn't make a mistake.  In this particular case, it's true that the compiler knows the value of px at compile time because it's in the declaration but, if the compiler accepted that array construction, what would the compiler do if px had not been initialized in its declaration ?... of course, the only thing it could do is complain and refuse the statement.  That would be confusing because sometimes the construction would be accepted and an identical construction would not be accepted because the variable had not been initialized.

The real problem is that an array must be initialized with _constants_ and since px is a variable, whatever value it's initial value may be, it is _not_ a constant.  (it may not have even been initialized.)

Succinctly, compile time initializations cannot be done with variables, only constants.

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

clerfayt

  • Newbie
  • Posts: 5
Re: initialization of array of pointers
« Reply #6 on: April 05, 2021, 08:18:33 am »
Thank you all for your replies!
I understand the problem now. The address of a variable is a constant, the pointer (usually) isn't.
 :)

440bx

  • Hero Member
  • *****
  • Posts: 4029
Re: initialization of array of pointers
« Reply #7 on: April 05, 2021, 09:05:50 am »
the pointer (usually) isn't.
 :)
Just to be very precise, the address of the pointer is constant (which is why you can do @x) but what it points to may not be (px can point to x or any other variable of type PReal in your example.)
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

PascalDragon

  • Hero Member
  • *****
  • Posts: 5481
  • Compiler Developer
Re: initialization of array of pointers
« Reply #8 on: April 05, 2021, 11:30:45 am »
The reason "arr: ArrayOfPReal = (@x, px); {Illegal expression}" is an illegal expression is because px is a _variable_ and the compiler cannot know the value held in px at compile time.

I just did a quick test. Unless I made a mistake, the compiler *does* know the value px has at compile time. I saw the value using -al. I think the compiler is being lazy and does not want to use the value. Or more accurately, the compiler was not taught how to do that, yet.

It does not know the value in the sense that it would be able to do a constant propagation, because that is only possible with untyped constants. This is by design.

engkin

  • Hero Member
  • *****
  • Posts: 3112
Re: initialization of array of pointers
« Reply #9 on: April 06, 2021, 06:53:31 am »
In this particular case, it's true that the compiler knows the value of px at compile time because it's in the declaration but, if the compiler accepted that array construction, what would the compiler do if px had not been initialized in its declaration ?... of course, the only thing it could do is complain and refuse the statement.

I don't think this is the only way the compiler has. If px was not initialized with a value, it is nil by default if declared as a global variable, or it holds some random value if declared as a local variable. The compiler could issue a hint or warning for the first case, and error for the second case.

That would be confusing because sometimes the construction would be accepted and an identical construction would not be accepted because the variable had not been initialized.

The situation we have today is the confusing one. The compiler accepted @x and refused an equal value because it came from a variable px that hold the same value. This question is an example.

The real problem is that an array must be initialized with _constants_ and since px is a variable, whatever value it's initial value may be, it is _not_ a constant.  (it may not have even been initialized.)

The array is initialized with constants in both cases. The value px holds at the time of initialization is a constant. The compiler could alert the programmer when this variable is not initialized.

 
Succinctly, compile time initializations cannot be done with variables, only constants.

Other than design decision, I don't see what makes it impossible.
« Last Edit: April 06, 2021, 06:55:04 am by engkin »

engkin

  • Hero Member
  • *****
  • Posts: 3112
Re: initialization of array of pointers
« Reply #10 on: April 06, 2021, 07:03:23 am »
The reason "arr: ArrayOfPReal = (@x, px); {Illegal expression}" is an illegal expression is because px is a _variable_ and the compiler cannot know the value held in px at compile time.

I just did a quick test. Unless I made a mistake, the compiler *does* know the value px has at compile time. I saw the value using -al. I think the compiler is being lazy and does not want to use the value. Or more accurately, the compiler was not taught how to do that, yet.

It does not know the value in the sense that it would be able to do a constant propagation, because that is only possible with untyped constants. This is by design.

Just to make it clear, I do not want this to be added to the compiler. It is more of an abstract question on my side to see what really prevents adding it to the compiler. Your answer seems to indicate that it is possible but not wanted.

PascalDragon

  • Hero Member
  • *****
  • Posts: 5481
  • Compiler Developer
Re: initialization of array of pointers
« Reply #11 on: April 06, 2021, 09:06:03 am »
That would be confusing because sometimes the construction would be accepted and an identical construction would not be accepted because the variable had not been initialized.

The situation we have today is the confusing one. The compiler accepted @x and refused an equal value because it came from a variable px that hold the same value. This question is an example.

No, it's not confusing. It's stated essentially everywhere that typed constants are essentially not constants, but variables (no matter if $J+ or $J-). Thus expecting that the value of a type constant is propagated is simply wrong.

The real problem is that an array must be initialized with _constants_ and since px is a variable, whatever value it's initial value may be, it is _not_ a constant.  (it may not have even been initialized.)

The array is initialized with constants in both cases. The value px holds at the time of initialization is a constant. The compiler could alert the programmer when this variable is not initialized.

px is not a constant from the compiler's point of view.

The reason "arr: ArrayOfPReal = (@x, px); {Illegal expression}" is an illegal expression is because px is a _variable_ and the compiler cannot know the value held in px at compile time.

I just did a quick test. Unless I made a mistake, the compiler *does* know the value px has at compile time. I saw the value using -al. I think the compiler is being lazy and does not want to use the value. Or more accurately, the compiler was not taught how to do that, yet.

It does not know the value in the sense that it would be able to do a constant propagation, because that is only possible with untyped constants. This is by design.

Just to make it clear, I do not want this to be added to the compiler. It is more of an abstract question on my side to see what really prevents adding it to the compiler. Your answer seems to indicate that it is possible but not wanted.

While it's indeed not wanted it's also not possible, because typed constants are handled totally different from true constants and thus the compiler does not know their value.

440bx

  • Hero Member
  • *****
  • Posts: 4029
Re: initialization of array of pointers
« Reply #12 on: April 06, 2021, 04:38:03 pm »
I don't think this is the only way the compiler has. If px was not initialized with a value, it is nil by default if declared as a global variable, or it holds some random value if declared as a local variable. The compiler could issue a hint or warning for the first case, and error for the second case.
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.

The situation we have today is the confusing one. The compiler accepted @x and refused an equal value because it came from a variable px that hold the same value. This question is an example.
It's not confusing because in one case it's a constant (@x) and in the other it's a variable (px^). 

The array is initialized with constants in both cases. The value px holds at the time of initialization is a constant. The compiler could alert the programmer when this variable is not initialized.
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.


Other than design decision, I don't see what makes it impossible.
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.)

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. 

Maybe it is possible to implement it but, the number of difficult problems and complications it creates is significant. 
(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: 6686
Re: initialization of array of pointers
« Reply #13 on: April 06, 2021, 05:52:36 pm »
It's not confusing because in one case it's a constant (@x) and in the other it's a variable (px^). 

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.

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: 4029
Re: initialization of array of pointers
« Reply #14 on: April 06, 2021, 06:12:00 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)
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

 

TinyPortal © 2005-2018