Byte madness
Blitz3D Forums/Blitz3D Beginners Area/Byte madness
| ||
Okay I´m gonna post this in the beginners portion just bc of the nature of this despite I´m by no means a beginner but this just makes me scream out of embarrassment while debugging. Can you please spot the buggie? D prints 256 not 255 as expected? PRINT dd and you get 255, or move the print D inside the loop, and you get 255. ) Why does it show d show up as 256? what have I´ve been missing? ; fun packing unpacking bytes ; example that tests all 4 bytes For a = 0 To 255 For b = 0 To 255 For c = 0 To 255 For d = 0 To 255 aa=a : bb=b : cc=c : dd=d ; we keep the original values value = a Shl 24 + b Shl 16 + c Shl 8 + d ; PACK IT into an integer a = value Shr 24 And 255 : b = value Shr 16 And 255 : c = value Shr 8 And 255 : d = value And 255 ; now UNPACKing ; quit if anything did go wrong with the bytes If aa<>a Then End If bb<>b Then End If cc<>c Then End If dd<>d Then End ; print d ; this would show 0-255, never 256 ;Print "--------" Next : Next : Next : Delay 1 : Print d: Next ; this d DOES show only 256? Print "All went well" : WaitKey |
| ||
I'm not 100 percent sure what you're trying to achieve, but I just found that swapping 255 in all of the For loops to 254 gives 255 as a result. |
| ||
This is the nature of loops. `Next` increments its associated variable, then checks if it's still in range. On the 256th run through `Next`, d is incremented to 256, fails the test, and the loop ends. Ideally you should never rely on the value of a loop index variable after its associated loop ends, or assume it will hold any particular value, since this is an undocumented implementation detail (and in theory, could change; there are other ways to implement a loop). The loop's over, the variable isn't being used for that any more. Set it to a new value or just don't use it. (Are you forgetting that the `d` loop ends with the first `Next`, not the last?) |
| ||
I´m trying to figure out why one see the counter go beyond the FOR NEXT loop. Why 256 even pops up there. It should not. By all means you can put eg 254 there, but then why does it show 255 then, it is the same problem. |
| ||
Yasha I see. I´m just about trying to grasp this concept I´ve actually never seen or HAD to think about this before. Is this common on all platforms and dialects? It feels like a bug, really, to me but I´m very confused about this discovery right now. It never occured to me before. |
| ||
Well the variable has to have some value... it's only within the loop itself that you said it specifically has to be one of the following ones. After the loop, you haven't actually told it what you want the variable to hold, so anything is valid (and therefore the value is meaningless). In other languages (e.g. BlitzMax and C) you'd usually scope the variable declaration to the `For` and you wouldn't even be able to access it from outside, thus eliminating the question. You can't do that in B3D, sadly. |
| ||
0 to 255 is a range of 256, don't forget zero is included in the loop. |
| ||
So this would mean that all code inbetween a NEXT and its respective FOR actually contains +1 or +STEP? I guess this makes sense for all other values before the last one. Still need to wrap my head around this. C++ also has this then without me evert noticing it? haha I´m glad to find out finally. This could otherwise have created some truly nasty bugs. EDIT: Ahh scoping coming into sensible use, nice. |
| ||
Steve true, the 0 vs 1 in loops I´ve known and used that all my life most coders learns that pretty quickly (or HAVE to rather) still, this "detail" flew right above my head. |
| ||
Thanks guys for clearing this up. Really appreciated. I was going nuts. |
| ||
Rewriting as a while loop with the same functionality may make it clearerx=0 while (x<256) 'i.e. 0->255, same as for loop version print x ' will print 0->255 x=x+1 wend print x ' will print 256 due to final increment which failed 'x<256' test |
| ||
;; Hi Jimmy, ;; That's the nature of FOR loops in almost any language (C, C++, BASIC,...), ...; ;; (It's my opinion that the last value of "a=256", shall remain stable, and you can depend on it for coding logic.) For a = 0 To 255 ;; When "a" increments past segment [0..255] ;; then this loop shall exit past "next" Next ;; --- You might like REPEAT...UNTIL loops :) z=0 ;;;;; Repeat z = z +1 Until z=255 ;; In the case of a REPEAT...UNTIL block, "z" shall remain ;; at value 255, and shall not proceed to 256 . Delay(10) ;; ;; .. On the other hand, here is a way for a FOR loop to stay in segment [0..255] : (Depend on "aa" instead.) For a=0 to 255 aa = a next ;; ---> "aa" shall stop at value 255, even though "a" runs away to 256. End |
| ||
One of the only things I learned in a programming subject I did at university 20 years ago was this: Never ever count on the value of a for loop counter being what you expect after exiting the loop. |
| ||
; fun packing unpacking bytes ; example that tests all 4 bytes For a = 0 To 255 For b = 0 To 255 For c = 0 To 255 For d = 0 To 255 aa=a : bb=b : cc=c : dd=d ; we keep the original values value = a Shl 24 + b Shl 16 + c Shl 8 + d ; PACK IT into an integer a = value Shr 24 And 255 : b = value Shr 16 And 255 : c = value Shr 8 And 255 : d = value And 255 ; now UNPACKing ; quit if anything did go wrong with the bytes If aa<>a Then End If bb<>b Then End If cc<>c Then End If dd<>d Then End ; print d ; this would show 0-255, never 256 ;Print "--------" Next ; This is Next of the d Loop. What happens here internaly? d=d+Step (Step=1 in your case) ... if d <= 255 the Loop continues ... otherwise ends ... So it must be bigger than 255 ! Next ; This is Next of the c Loop. Next ; This is Next of the b Loop. Delay 1 Print d Next ; This is Next of the a Loop. this d DOES show only 256? Yes It should ... otherwise the d loop above would never end Print "All went well" : WaitKey See the comment after Next in your code ... Use Indentation ... and remember ... Your Logic may not always be the Logic of the System ;-) If you do not know how Next works internaly you cannot expect to be right with a statement ... *d should be 255* !? Btw: In Blitz you can rely on the content of a Variable after exiting a Loop. Its exact the result of the last internal calculation ... and it does not get changed as long as you don't write code which changes the variable. Below is the Code translated to assembler Note the section _18 ; Next starts here add [ebp-16],1 ; Adds 1 _13 cmp [ebp-16],255 ; Compares with 255 ( For d = 0 to 255 ) jle _14 ; Jump to Label _14 when lower or equal BlitzCC V11.8 (C)opyright 2000-2003 Blitz Research Ltd Compiling "D:\Downloads\20150101\!B3D\Jimmy.bb" Parsing... Generating... Translating... .align 16 __MAIN push ebx push esi push edi push ebp mov ebp,esp sub esp,36 sub esp,4 mov eax,__DATA mov [esp],eax call __bbRestore sub esp,4 mov eax,__LIBS mov [esp],eax call __bbLoadLibs call _2_begin jmp _2_leave _2_begin mov ebx,0 mov [ebp-4],ebx mov [ebp-8],ebx mov [ebp-12],ebx mov [ebp-16],ebx mov [ebp-20],ebx mov [ebp-24],ebx mov [ebp-28],ebx mov [ebp-32],ebx mov [ebp-36],ebx mov [ebp-4],0 jmp _7 _8 mov [ebp-8],0 jmp _9 _10 mov [ebp-12],0 jmp _11 _12 mov [ebp-16],0 jmp _13 _14 mov ebx,[ebp-4] mov [ebp-20],ebx mov ebx,[ebp-8] mov [ebp-24],ebx mov ebx,[ebp-12] mov [ebp-28],ebx mov ebx,[ebp-16] mov [ebp-32],ebx mov ebx,[ebp-4] shl ebx,byte 24 mov esi,[ebp-8] shl esi,byte 16 add ebx,esi mov esi,[ebp-12] shl esi,byte 8 add ebx,esi add ebx,[ebp-16] mov [ebp-36],ebx mov ebx,[ebp-36] shr ebx,byte 24 mov esi,255 and ebx,esi mov [ebp-4],ebx mov ebx,[ebp-36] shr ebx,byte 16 mov esi,255 and ebx,esi mov [ebp-8],ebx mov ebx,[ebp-36] shr ebx,byte 8 mov esi,255 and ebx,esi mov [ebp-12],ebx mov ebx,[ebp-36] mov esi,255 and ebx,esi mov [ebp-16],ebx mov ebx,[ebp-4] cmp [ebp-20],ebx jz _15 call _fend _15 mov ebx,[ebp-8] cmp [ebp-24],ebx jz _16 call _fend _16 mov ebx,[ebp-12] cmp [ebp-28],ebx jz _17 call _fend _17 mov ebx,[ebp-16] cmp [ebp-32],ebx jz _18 call _fend _18 add [ebp-16],1 _13 cmp [ebp-16],255 jle _14 _6 add [ebp-12],1 _11 cmp [ebp-12],255 jle _12 _5 add [ebp-8],1 _9 cmp [ebp-8],255 jle _10 _4 sub esp,4 mov [esp],1 call _fdelay sub esp,8 mov eax,[ebp-16] mov [esp],eax call __bbStrFromInt mov [esp],eax call _fprint add [ebp-4],1 _7 cmp [ebp-4],255 jle _8 _3 sub esp,8 mov eax,_19 mov [esp],eax call __bbStrConst mov [esp],eax call _fprint call _fwaitkey ret _2_leave mov esp,ebp pop ebp pop edi pop esi pop ebx ret word 0 _19 .db "All went well",0 .align 4 __LIBS .db "",0 .align 4 __DATA .dd 0 Assembling... |
| ||
@RGR That's neat how you got the assemebly language there. How did you do it? |
| ||
Create a batch file BlitzCC.bat inside the bin Folder (easiest way) like that:blitzcc -a -c D:\SourcePath\SourceFile.bb >D:\DestinationPath\DestinationFile.asm Doubleclick the batchfile. SourcePath and DestinationPath, SourceFile and DestinationFile can be the same if they have different file extensions as shown above. Use Paths/Filenames with no blanks ... otherwise you have to use quotation marks. .asm is a textfile you can view with any texteditor (I use Crimson Editor) |
| ||
Thanks for great feedback ! Hi John Galt and Virtland Acatually I really like those loop analogies you both gave there, nice stuff Thanks. Matty that´s a good rule. RGR Interesting stuff ! |