Problem with pointers arithmetic

Beta Testing discussion on mikroPascal PRO for AVR.
Author
Message
JohannesH
Posts: 68
Joined: 23 Apr 2007 07:51

#16 Post by JohannesH » 12 Dec 2008 12:42

@jpc
sorry to say so , this is not at all related to beta-testing , the pointer to constant allways had to be declared this way and finds its origin in de different memory-access for ROM and RAM on PIC.
Because it allways had to be done this way does not replace the need for proper documentation.

Maybe you are in the wrong forum here, its NOT PIC related.
This is the forum for the beta version of AVR Pascal.

Johannes

octal
Posts: 534
Joined: 09 Feb 2005 14:15
Location: France
Contact:

#17 Post by octal » 16 Dec 2008 17:24

Still no answer to my first post related to Pointer arithmetic problem :(
http://www.pocketmt.com

User avatar
zristic
mikroElektronika team
Posts: 6608
Joined: 03 Aug 2004 12:59
Contact:

#18 Post by zristic » 17 Dec 2008 08:37

octal wrote:Still no answer to my first post related to Pointer arithmetic problem
Hi octal,

In the sea of essays on this topic I really could not understand what your question was.

It would be great if you could formulate a short question, in few sentences please.

I read the topic twice, but I could not understand what your question was :oops: except that you complain about the declaration of the pointer to constant.

octal
Posts: 534
Joined: 09 Feb 2005 14:15
Location: France
Contact:

#19 Post by octal » 17 Dec 2008 10:20

Hello zristic,

Sorry if my posts bothered you :(

I have no complains about pointers to constants. Forgot the various posts.

Read only first post. I just wanted to know why the compiler give complains about using "+" operator when using pointers to constants in arithmetic operations. It seems to accept "-" instead.

I need that to be able to access my array of constants without going down to asm code and index registers for portability reasons.

Regards
octal
http://www.pocketmt.com

User avatar
zristic
mikroElektronika team
Posts: 6608
Joined: 03 Aug 2004 12:59
Contact:

#20 Post by zristic » 17 Dec 2008 10:33

Got it now, thanks for pointing me to the right post.

The problem is detected and it is quickly fixed. The update will follow this week.

Thanks for the reports and remember to keep them short and concise.

octal
Posts: 534
Joined: 09 Feb 2005 14:15
Location: France
Contact:

#21 Post by octal » 17 Dec 2008 10:39

Ok
Thanks for your prompt answer.
I'll wait for the new beta to be published.

regards
octal
http://www.pocketmt.com

User avatar
srdjan
mikroElektronika team
Posts: 1552
Joined: 28 Dec 2005 12:47
Location: Serbia

#22 Post by srdjan » 17 Dec 2008 13:28

Hi,
Regarding the first post code problem.

Problem:
mikroPascal does all right side expression calculations according to the left side.

Code: Select all

CurCharData := xGlcdSelFont+(i*xGlcdSelFontNbRows)+j+cOffset; 
That is why, in the line above, subexpression (i*xGlcdSelFontNbRows) will give pointer type temporary result (because leftside is pointer). Then you get to add two pointers, which is not allowed and that's the problem.
Basically, you are mixing pointer and integer types in additive expression. What you need to do when you have such "exhibitions" in your code is to explicitly cast subexpressions you do not want to be evaluated according to the left side type.
In this case,

Code: Select all

CurCharData := xGlcdSelFont+dword(i*xGlcdSelFontNbRows)+j+cOffset; 
Additional explanation:
Adding pointers is not allowed, because this way you get meaningless result.
Substraction of the pointers, on the other hand, can give you useful result, that is why it is allowed i.e. if pointers are pointing to two different elements of one array, by subtracting them you can get number of elements between these two array elements.

janni
Posts: 5373
Joined: 18 Feb 2006 13:17
Contact:

#23 Post by janni » 17 Dec 2008 18:53

Oh my, aren't we in trouble :cry: . Next thing we know, we'll be able only to compare pointers (it's Pascal, after all :wink: ). And all indirect addressing shortcuts will have to be done using assembly...

BTW, have I got it right from the example? This (let's assume i,j as byte)

Code: Select all

 VarPtr:=VarPtr+i+j;
seems to be OK (no 'temporary' result).

This

Code: Select all

 VarPtr:=VarPtr+(2*i);
is apparently wrong.

What about this?

Code: Select all

 VarPtr:=VarPtr+(i+j);
Will it lead to 'temporary pointer'?

Seriously, this 'no pointer addition' rule is unnecessary and obviously leads to more trouble than it's worth (one may easily obtain meaningless results even with this rule 'protection'). Either one may modify pointers as one wishes - with all it's riscs, or not at all. In other words, either we have Pascal for embeded systems, or pure Pascal for systems with virtually infinite resources where pointers are fully protected.

octal
Posts: 534
Joined: 09 Feb 2005 14:15
Location: France
Contact:

#24 Post by octal » 18 Dec 2008 13:34

srdjan wrote:Hi,
Regarding the first post code problem.

Problem:
mikroPascal does all right side expression calculations according to the left side.

Code: Select all

CurCharData := xGlcdSelFont+(i*xGlcdSelFontNbRows)+j+cOffset; 
That is why, in the line above, subexpression (i*xGlcdSelFontNbRows) will give pointer type temporary result (because leftside is pointer).
Sorry to say that this is absurd (at least for me) :?

I absolutely dont agree about this. I dont know which pascal reference you are using but this cannot be correct at all.

The logic would be that we check and apply type conversions LOCALLY between operand, I mean that an operator return type should be deduced from its operands, and not from a left side (lvalue) assignement type.
Once all operations finished, the FINAL result of the expression should be casted or transformed to be compatible with the LValue (as if the assignement was a simple binary operator itself).

if we use your implementation logic, means that each partial evaluation of part of an expression is systematically converted to LValue type, this kind of operation would give systematically erronous result:

Code: Select all

procedure calc;
var i, j : integer;
     k : byte;
begin
  ...
  // for some reason  j := 258;
  // for some reason  i := 1;
  k := (j - i) - 6 ;
end;

if for some reason j = 258 and i = 1 (for example from reading ports values), as i and j are integers, (j-i) is a partial result (=257) and since the lValue is Byte, this partial value is casted to byte wich means it will be equal to 1. and the result of k will be = -5 (or its complement).

The correct way should have been

STEP1:
j - i => minus operator between two integers give an integer = 257.
STEP2:
(i-j=257) temporary - 6 => minus operator between Integer and Byte => either do it directly or convert Byte to Integer, and apply Minus operator between two integers
the result should be 257(as integer) - 6 (as integer)= 251 as integer

STEP3:
Assignment operator of Integer(result of expression) to Byte (k), => convert the integer to byte (mostly take LSB)
which make
k := LowByte of (251 integer) = 251

and this is the correct result.

I dont know which reference of Pascal you are using for managing Pointers but I think that Pointers should be handled the same way as Word variables.


srdjan wrote: Additional explanation:
Adding pointers is not allowed, because this way you get meaningless result.
Substraction of the pointers, on the other hand, can give you useful result, that is why it is allowed i.e. if pointers are pointing to two different elements of one array, by subtracting them you can get number of elements between these two array elements.
I dont agree with that either.
Substraction has is absolutely as dangeourous as addition.
when you say that it gives the number of elemnts in between two array elements, first this assumes two things:
1- The arrays are allocated with incrementing addresses. That means that if someday the allocations scheme changes this will fail.
2- this assumes that all items in the array are 1 byte size.

To avoid this, all developers use Sizeof() like operator or function. If we assume the user has the responsability to manage the range checking by hand (which is 99% the case in all embedded world compilers) when he do substration of pointers, I dont understand why he do not do that for addition of pointers. The problem is absolutely the same.

I think that Janni comment is close to what developers need in embedded world. Please, make pointers arithmetic the same (compatible) with words or unsigned integers arithmetic, and change the sub-expressions casting logic. After all, when a user wants to explicitely force the cast of a sub expression to any type (even the Lvalue type if he want), he still have the possibility to use dedicate cast functions.

Regards
octal
http://www.pocketmt.com

User avatar
srdjan
mikroElektronika team
Posts: 1552
Joined: 28 Dec 2005 12:47
Location: Serbia

#25 Post by srdjan » 18 Dec 2008 16:58

octal wrote:
srdjan wrote: Additional explanation:
Adding pointers is not allowed, because this way you get meaningless result.
Substraction of the pointers, on the other hand, can give you useful result, that is why it is allowed i.e. if pointers are pointing to two different elements of one array, by subtracting them you can get number of elements between these two array elements.
I dont agree with that either.
Substraction has is absolutely as dangeourous as addition.
when you say that it gives the number of elemnts in between two array elements, first this assumes two things:
1- The arrays are allocated with incrementing addresses. That means that if someday the allocations scheme changes this will fail.
2- this assumes that all items in the array are 1 byte size.
1. I did say "if pointers are pointing to two different elements of ONE" (the same) "array".
2. noup. It will be like that for all array element types.
octal wrote: After all, when a user wants to explicitely force the cast of a sub expression to any type (even the Lvalue type if he want), he still have the possibility to use dedicate cast functions.
This is exactly the point. If some users do not like your approach they will have to use dedicated cast functions in order to do what they want.

It will stay like this for this release for sure. In future releases, we will revise the way the right side expressions are evaluated when left side is of pointer type (only). The other issues you were referring to (including pointer arithmetics, we may forbid subtraction if majority of users insists) will remain as mikroE Pascal/Basic compiler specifics.
After a while, when users become familiar with our approach, we will do a survey and see what users think of it and make necessary changes to suite the user needs. After all, we are here to please the users.
Thank you for understanding.

octal
Posts: 534
Joined: 09 Feb 2005 14:15
Location: France
Contact:

#26 Post by octal » 18 Dec 2008 17:05

Hello srdjan,
thank you for your answer.
I think that substration (-) should be also forbiden to make things homogenous as you suggest. I dont think users need for such thing. maybe if needed, you could add a specific internal function for that to count number of items in an interval. It's a safer way. You are better placed to do the choice, no need to wait for users survey.
Also it would be nice, if time permits, to add more details on the documentation related to pointers specifics and authorised operations.

Regards
octal
http://www.pocketmt.com

janni
Posts: 5373
Joined: 18 Feb 2006 13:17
Contact:

#27 Post by janni » 18 Dec 2008 18:43

Srdjan, where does this need to reduce programming freedom come from? Did users really complain that compiler does not check whether pointers are being added?

There is no pointer arithmetics in Pascal, so discussion about what should be forbidden and what not does not make much sense. Any decision will be arbitrary and outside of Pascal definition. Just remember that we're dealing with embeded systems where pointers play broader role and programmers are supposed to know the hardware.

I think that all most users do is simple pointer assignment to constant or variable. Those certainly do not need any 'protection' rules. Some, on the other hand, may need to do some pointer arithmetics to use all the possibilities of processors used. Already, in older compilers' versions, we have a fload of meaningless warnings about using 'integral value' with pointers. If it was decided that pointers' arithmetics is possible, then one would rather expect this decision to go all the way - to enable explicit typecasting of pointers and use of any applicable operators, like with any other simple type, rather than to introduce arbitrary limitations in the name of general 'safety'. (BTW, forbidding pointers addition while at the same time allowing to add any value of other type to pointer does not seem to be a reasonable action.)

I'd regard this

Code: Select all

   Ptr1:=Ptr1+pointer(8*i);
safer (at least the compiler 'sees' that I know what I'm doing) than this

Code: Select all

   Ptr1:=Ptr1+dword(8*i);
In the first case there'll be no need for meaningless warnings. It could also work for both ROM and RAM pointers, unlike the other one. Naturally, the compiler may check if the result isn't outside of memory range (whether RAM or ROM) and such check would indeed make the user feel safer.

Post Reply

Return to “mikroPascal PRO for AVR Beta Testing”