Cautions when using For:Next loops

General FreeBASIC programming questions.
Post Reply
Richard
Posts: 3096
Joined: Jan 15, 2007 20:44
Location: Australia

Cautions when using For:Next loops

Post by Richard »

Firstly:
For Next loops will not terminate at the end of a data type range because overflow is not flagged when the counter variable is stepped prior to the range validity test.
For "Byte" = -128 to 126 works but
For "Byte" = -128 to 127 is an infinite loop because +128 is -128 in Byte.
For "Ubyte" = 0 to 255 is also an infinite loop
If you want to generate all values of a Byte variable you can use a longer datatype and type convert, then assign.

Code: Select all

For variable As Byte = 120 To 126 ' change To 127 and it will infinitely loop
    Print variable;" ";
Next variable
Print
sleep
Secondly:
Both Integer and Uinteger do work with negative steps, but if the counter variable is of type Ubyte or Ushort then it fails to run with negative steps. I think it might be because the negative literal step is cast and stored as temporary unsigned. This can be viewed as either incomplete compiler code, a bug or an undocumented restriction.

Code: Select all

print
Print "Loop with Ubyte and negative stepsize"
For variable As Ubyte = 38 To 16 step -1
    Print variable;" ";
Next variable
Print
Print
Print "Loop with Ushort and negative stepsize"
For variable As Ushort = 38 To 16 step -1
    Print variable;" ";
Next variable
Print
Sleep
Thirdly:
For, Next and Step literals appear not to be checked for type range at compile time. You get no warning of type conversion. Here are two examples.

Code: Select all

Print
Print "This will not execute because -130 is +126 as a signed byte"
For variable as byte = -130 To 16
    Print variable;" ";
Next variable
Print
' This next executes from 12 to 16
Print
Print "-500 is +12 in Byte so we get"
For variable as byte = -500 To 16
    Print variable;
Next variable
Sleep
So take care when using For:Next loops.
integer
Posts: 408
Joined: Feb 01, 2007 16:54
Location: usa

Post by integer »

Thirdly:
For, Next and Step literals appear not to be checked for type range at compile time. You get no warning of type conversion. Here are two examples.
from the freebasic manual
The CUByte function rounds off the decimal part and returns a 8 bit UByte value. The function does not check for an overflow, so be sure not to pass a value thats less/larger then 0 to 255. The name can be explained as 'Convert to Unsigned Byte'.
I know you are not addressing decimals, however that statement from
the FB manual also implies and means (at least to me) that integer or unsigned values outside the range of the byte (0 to 255) with be MOD the byte range limits.
This can be viewed as either incomplete compiler code, a bug or an undocumented restriction.
I see no fault with the compiler output.
Just my view.
MichaelW
Posts: 3500
Joined: May 16, 2006 22:34
Location: USA

Post by MichaelW »

In a 32-bit application it would be normal to use a 32-bit counter. Perhaps 8-bit counters do not work because making them work was deemed not worth the effort. The only possible benefit that I can see would be a reduction in code size, but in a normal app the reduction would not be significant. Counters are best stored in registers, and using partial registers (8-bit or 16-bit) can interfere with the processor’s ability to execute instructions out of order, and thus decrease performance.
anonymous1337
Posts: 5494
Joined: Sep 12, 2005 20:06
Location: California

Post by anonymous1337 »

safety pwnage.

Code: Select all

for i as ubyte = 0 to 255
'' do stuff
'' OWNED
if i = 255 then exit for
next
steven522
Posts: 265
Joined: May 27, 2005 13:02
Location: Alabama, USA
Contact:

Post by steven522 »

Code: Select all

for i as ubyte = 0 to 255
'' do stuff
'' OWNED
if i > 254 then exit for
next
...just because you never know what "do stuff" might actually do...
anonymous1337
Posts: 5494
Joined: Sep 12, 2005 20:06
Location: California

Post by anonymous1337 »

steven522 wrote:...just because you never know what "do stuff" might actually do...
Well if it's any greater than 255 it just resets back because of overflow. It's either at 255, or it is below. There's no way around that.

Thus, if = 255 is just as good as if > 254. Think of it as how pointless if >= 255 would be in this scenario.
Richard
Posts: 3096
Joined: Jan 15, 2007 20:44
Location: Australia

Post by Richard »

Firstly:
There is no question that anonymous1337s terminal condition is the work-around to stop the counter falling off the edge of the universe. Full marks to anonymous1337 for this solution. Steven522 presented a more universal solution, but failed to make the point clearly that if the step size was not unity you would need to test for the range near the limit. Assuming positive stepsize; If step was 2 then you would use "If i > 253 Then Exit For".
Or for Ubyte more generally: "If i > (255 - stepsize) Then Exit For"
Secondly:
Cars have a reverse gear so they can go backwards. Bicycles do not. Is Ubyte the closest thing there is to a bicycle in FreeBASIC, Ushort then would be a motorcycle!
Thirdly:
Literal type checking does occur during compile with "error 5, implicit conversion" warnings, but not in For:Next literals.
counting_pine
Site Admin
Posts: 6323
Joined: Jul 05, 2005 17:32
Location: Manchester, Lancs

Post by counting_pine »

One thing FBC could do is warn you when you give a constant bound that can't be checked properly. I think there was talk about it a while back, but I don't know what was decided, if anything.
You could try adding a feature request on sourceforge.net.
Post Reply