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