Cautions when using For:Next loops

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

Cautions when using For:Next loops

Postby Richard » Apr 13, 2007 9:17

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: 379
Joined: Feb 01, 2007 16:54
Location: usa

Postby integer » Apr 13, 2007 13:08

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

Postby MichaelW » Apr 13, 2007 13:55

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.
Pritchard
Posts: 5492
Joined: Sep 12, 2005 20:06
Location: Ohio, USA

Postby Pritchard » Apr 13, 2007 16:06

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:

Postby steven522 » Apr 13, 2007 18:23

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...
Pritchard
Posts: 5492
Joined: Sep 12, 2005 20:06
Location: Ohio, USA

Postby Pritchard » Apr 13, 2007 18:40

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: 2953
Joined: Jan 15, 2007 20:44
Location: Australia

Postby Richard » Apr 13, 2007 21:50

Firstly:
There is no question that Pritchards terminal condition is the work-around to stop the counter falling off the edge of the universe. Full marks to Pritchard 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: 6170
Joined: Jul 05, 2005 17:32
Location: Manchester, Lancs

Postby counting_pine » Apr 14, 2007 1:39

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.

Return to “General”

Who is online

Users browsing this forum: Baidu [Spider], jevans4949 and 3 guests