8
votes

I can write for..do process for integer value.. But I can't write it for int64 value. For example:

var
  i:int64;
begin
  for i:=1 to 1000 do 
end; 

The compiler refuses to compile this, why does it refuse?

4
I cant see an error.also program cant start..musti
+1 because this is an academic question, I see so and so behavior. I would have expected it to work, but it does not.... why is this I wonder. Rather than a I really need to do trillions of iterations in my loop kind of question.Johan
"Academically", you can make a compelling argument that you should only ever use a "while" loop.paulsm4
Does compiler chokes on this code silently?OnTheFly

4 Answers

9
votes

The Delphi compiler simply does not support Int64 loop counters yet.

5
votes

Loop counters in a for loop have to be integers (or smaller).
This is an optimization to speed up the execution of a for loop.

Internally Delphi always uses an Int32, because on x86 this is the fastest datatype available.
This is documented somewhere deep in the manual, but I don't have a link handy right now.

If you must have a 64 bit loop counter, use a while..do or repeat..until loop.

3
votes

Even if the compiler did allow "int64" in a Delphi 7 for-loop (Delphi 7???), it probably wouldn't complete iterating through the full range until sometime after the heat death of the Sun.

So why can't you just use an "integer"?

If you must use an int64 value ... then simply use a "while" loop instead.

Problem solved :)

2
votes

Why to use a Int64 on a for-loop?

Easy to answer:

  • There is no need to do a lot of iterations to need a Int64, just do a loop from 5E9 to 5E9+2 (three iterations in total).
  • It is just that values on iteration are bigger than what Int32 can hold

An example:

procedure Why_Int64_Would_Be_Great_On_For_Loop;
const
     StartValue=5000000000; // Start form 5E9, 5 thousand millons
     Quantity=10; // Do it ten times
var
   Index:Int64;
begin
     for Index:=StartValue to StartValue+Quantity-1
     do begin // Bla bla bla
             // Do something really fast (only ten times)
       end;
end;

That code would take no time at all, it is just that index value need to be far than 32bit integer limit.

The solution is to do it with a while loop:

procedure Equivalent_For_Loop_With_Int64_Index;
const
     StartValue=5000000000; // Start form 5E9, 5 thousand millons
     Quantity=10; // Do it ten times
var
   Index:Int64;
begin
     Index:=StartValue;
     while Index<=StartValue+Quantity
     do begin // Bla bla bla
             // Do something really fast (only ten times)
             Inc(Index);
       end;
end;

So why the compiler refuses to compile the foor loop, i see no real reason... any for loop can be auto-translated into a while loop... and pre-compiler could do such before compiler (like other optimizations that are done)... the only reason i see is the lazy people that creates the compiler that did not think on it.

If for is optimized and so it is only able to use 32 bit index, then if code try to use a 64 bit index it can not be so optimized, so why not let pre-compiler optimizator to chage that for us... it only gives bad image to programmers!!!

I do not want to make anyone ungry...

I only just say something obvious...

By the way, not all people start a foor loop on zero (or one) values... sometimes there is the need to start it on really huge values.

It is allways said, that if you need to do something a fixed number of times you best use for loop instead of while loop...

Also i can say something... such two versions, the for-loop and the while-loop that uses Inc(Index) are equally fast... but if you put the while-loop step as Index:=Index+1; it is slower; it is really not slower because pre-compiler optimizator see that and use Inc(Index) instead... you can see if buy doing the next:

// I will start the loop from zero, not from two, but i first do some maths to avoid pre-compiler optimizator to convert Index:=Index+Step; to Inc(Index,Step); or better optimization convert it to Inc(Index);
Index:=2; 
Step:=Index-1; // Do not put Step:=1; or optimizator will do the convertion to Inc()
Index:=Step-2; // Now fix, the start, so loop will start from zero
while Index<1000000 // 1E6, one millon iterations, from 0 to 999999
do begin
        // Do something
        Index:=Index+Step; // Optimizator will not change this into Inc(Index), since sees that Step has changed it's value before
   end;

The optimizer can see a variable do not change its value, so it can convert it to a constant, then on the increment assign if adding a constant (variable:=variable+constant) it will optimize it to Inc(variable,constant) and in the case it sees such constant is 1 it will also optimes it to Inc(variable)... and such optimizatons in low level computer language are very noticeble...

In Low level computer language: A normal add (variable:=variable1+variable2) implies two memory reads plus one sum plus one memory write... lot of work But if is a (variable:=variable+othervariable) it can be optimized holding variable inside the processor cache. Also if it is a (variable:=variable1+constant) it can also be optimized by holding constant on the processor cache And if it is (variable:=variable+constant) both are cached on processor cache, so huge fast compared with other options, no acces to RAM is needed.

In such way pre-compiler optimizer do another important optimization... for-loops index variables are holded as processor registers... much more faster than processor cache...

Most mother processor do an extra optimization as well (at hardware level, inside the processor)... some cache areas (32 bit variables for us) seen that are intensivly used are stored as special registers to fasten access... and such for-loop / while-loop indexes are ones of them... but as i said.. most mother AMD proccesors (the ones that uses MP technology does that)... i do not yet know any Intel that do that!!! such optimization is more relevant when multi-core and on super-computing... so maybe that is the reason why AMD has it and Intel not!!!

I only want to show one "why", there are a lot more... another one could be as simple as the index is stored on a database Int64 field type, etc... there are a lot of reasons i know and a lot more i did not know yet...

I hope this will help to understand the need to do a loop on a Int64 index and also how to do it without loosing speed by correctly eficiently converting loop into a while loop.

Note: For x86 compiles (not for 64bit compilation) beware that Int64 is managed internally as two Int32 parts... and when modifing values there is an extra code to do, on adds and subs it is very low, but on multiplies or divisions such extra is noticeble... but if you really need Int64 you need it, so what else to do... and imagine if you need float or double, etc...!!!