Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Bug or Feature?
#1
Hi Boriel, I ran into following Problem:
Code:
print at 17,0;(peek 3)*9
gives me back 247. Why is this a Problem? PEEK 3 is 255, so (PEEK 3)*9 should be calculated as 255*9=2295, so it looks like the result of this calculation is stored in UBYTE. No problem because PEEK gives back UBYTE, but a multiplication is a little bit more problematic.
Code:
dim c1 as uinteger
c1=peek(adr)
print c1*9
Works, but
Code:
dim c1 as ubyte
c1=peek(adr)
print c1*9
does not work. The same if I use such a calculation as Parameter for a sub.
Any chance to fix this?

Another Problem:
Code:
print at 17,0;1<<3+2
Usually bit shifting should have the highest poriority, not the addition, thats why the result is 1<<(3+2)=32, but it should be (1<<3)+2=10.
------------------------------------------------------------
http://lcd-one.da.ru redirector is dead
Visit my http://members.inode.at/838331/index.html home page!
Reply
#2
LCD Wrote:Hi Boriel, I ran into following Problem:
Code:
print at 17,0;(peek 3)*9
gives me back 247. Why is this a Problem? PEEK 3 is 255, so (PEEK 3)*9 should be calculated as 255*9=2295, so it looks like the result of this calculation is stored in UBYTE. No problem because PEEK gives back UBYTE, but a multiplication is a little bit more problematic.
Code:
dim c1 as uinteger
c1=peek(adr)
print c1*9
Works, but
Code:
dim c1 as ubyte
c1=peek(adr)
print c1*9
does not work. The same if I use such a calculation as Parameter for a sub.
Any chance to fix this?
Hmmm. I'm afraid not. This is a feature, the same way as in C, due to truncation. c1 is always uByte and you can't gues in compile time it's value, so there might be a chance that, effectively, c1 * 9 > 255. C does the same. What you get is (PEEK(x) * 9 bAND 0xFFh)
LCD Wrote:Another Problem:
Code:
print at 17,0;1<<3+2
Usually bit shifting should have the highest poriority, not the addition, thats why the result is 1<<(3+2)=32, but it should be (1<<3)+2=10.
I will check priorities, but I used C/C++ priorities. According to this Wikipedia article << and >> has lower priority than + and -
Reply
#3
boriel Wrote:Hmmm. I'm afraid not. This is a feature, the same way as in C, due to truncation. c1 is always uByte and you can't gues in compile time it's value, so there might be a chance that, effectively, c1 * 9 > 255. C does the same. What you get is (PEEK(x) * 9 bAND 0xFFh)
I understand, never meet such a problem in HiSoft BASIC, maybe because it has no BYTE/UBYTE type but INTEGER/UINTEGER, FLOAT and STRING. But good explaination.
boriel Wrote:I will check priorities, but I used C/C++ priorities. According to this Wikipedia article << and >> has lower priority than + and -
If I remember correctly, the Priority in FreeBASIC is that shifting (SHL/SHR) has higher priority than addition, only shifting and assigment (SHL=/SHR=) has very very low priority.

...I found only german priority list of FreeBASIC:
<!-- m --><a class="postlink" href="http://www.freebasic-portal.de/befehlsreferenz/ausdruecke-operatoren-384.html">http://www.freebasic-portal.de/befehlsr ... n-384.html</a><!-- m -->
------------------------------------------------------------
http://lcd-one.da.ru redirector is dead
Visit my http://members.inode.at/838331/index.html home page!
Reply
#4
LCD Wrote:
Code:
print at 17,0;(peek 3)*9
gives me back 247. Why is this a Problem? PEEK 3 is 255, so (PEEK 3)*9 should be calculated as 255*9=2295, so it looks like the result of this calculation is stored in UBYTE. No problem because PEEK gives back UBYTE, but a multiplication is a little bit more problematic.
Surely the solution is a cast?
Code:
print at 17,0;CAST(uInteger,(peek 3))*9

I haven't tried it, but that seems to me the logical way to kick it up to an integer over a byte type when it returns something smaller than you need?
Reply
#5
britlion Wrote:I haven't tried it, but that seems to me the logical way to kick it up to an integer over a byte type when it returns something smaller than you need?

Yes, this is it...
The description of cast was misleading, because I though, it works only with variables.
Welcome back, by the way,
------------------------------------------------------------
http://lcd-one.da.ru redirector is dead
Visit my http://members.inode.at/838331/index.html home page!
Reply
#6
Bump!
Have found english FreeBASIC precedence table which shows that SHL/SHR have higher priority than +/- or binary AND:
<!-- m --><a class="postlink" href="http://www.freebasic.net/wiki/wikka.php?wakka=OpPrecedence">http://www.freebasic.net/wiki/wikka.php ... Precedence</a><!-- m -->
------------------------------------------------------------
http://lcd-one.da.ru redirector is dead
Visit my http://members.inode.at/838331/index.html home page!
Reply
#7
boriel Wrote:Hmmm. I'm afraid not. This is a feature, the same way as in C, due to truncation. c1 is always uByte and you can't gues in compile time it's value, so there might be a chance that, effectively, c1 * 9 > 255. C does the same. What you get is (PEEK(x) * 9 bAND 0xFFh)

We already discussed this. It's not the same way as C. In fact, C does the calculation correctly. In both z88dk and gcc, this program:

Code:
#include <stdio.h>

int main (void) {
  unsigned char c = 255;        // This will have to do for PEEK 3 ;-)
  printf ("%d * 3 = %d\n", c, c * 9);
  return 0;
}

Outputs

Code:
255 * 3 = 2295

I still find zxb behaviour quite confusing regarding the lack of type promotion. I shouldn't have to typecast this:

Code:
Dim numAttrs as uInteger
Dim numLines as uByte
...
numAttrs = 32 * numLines

as I don't have to do it in either freeBasic or C... But in ZX Basic I have to explicitly typecast numLines to uInteger for it to work correctly, which I find quite awkward.
Reply
#8
na_th_an Wrote:
boriel Wrote:Hmmm. I'm afraid not. This is a feature, the same way as in C, due to truncation. c1 is always uByte and you can't gues in compile time it's value, so there might be a chance that, effectively, c1 * 9 > 255. C does the same. What you get is (PEEK(x) * 9 bAND 0xFFh)

We already discussed this. It's not the same way as C. In fact, C does the calculation correctly. In both z88dk and gcc, this program:

Code:
#include <stdio.h>

int main (void) {
  unsigned char c = 255;        // This will have to do for PEEK 3 ;-)
  printf ("%d * 3 = %d\n", c, c * 9);
  return 0;
}
Yes, that's right. My mistake: it was already discussed in other thread.
The problem of c * 9 is that 9 is taken as <int> in C, that depends on the compiler. For z88dk, <int> is 16 bits, for example.
As discussed previously, I could implement that behaviour, but that will increase memory usage and will have a performance impact. :?

Also, using
printf ("%d * 3 = %d\n", c, c * 9);
where c is a byte/char, is not correct (might work, but it's undefined behavior, isn it?).
c * 9 promotes to <int>, and that's ok, but c is a char, so the printf instruction should read:
printf ("%d * 3 = %d\n", (int)c, c * 9);
Reply
#9
I dunno, to be honest, I have never thought about this kind of issues Smile gcc compiles the sources without a warning, as z88dk does. Even Hisoft BASIC works in 16 bits for integer calculations. Anyways, %d stands for any numeric variable, doesn't it? (I really don't know)

I understand your concerns about memory / speed. But shouldn't the user be the one who's in charge of performing such optimizations?

Right away, you can fix the issue by explicit type-casting. What would be the possibility/feasibility of those options:

1.- A command line option / compiler directive to enable / disable type promotion.
2.- Type promotion by default but the user can typecast to reduce memory usage and increase speed (just the opposite of current behaviour)

Not that I can't live with the compiler as it is right now, of course. I have no problems if I have to typecast stuff myself.
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)