Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

File size calculation, Int64, and differences between 32bit and 64bit

I had problems with the following code:

var
  FileSize : Int64;
...
FileSize := Info.nFileSizeLow or (Info.nFileSizeHigh shl 32);

I expected it to work because of the Int64 type of the left side of the assignment. But it does not. The partial calculation containing the shl seems to produce an overflow.

So I changed it to:

FileSize := Info.nFileSizeLow or (Int64 (Info.nFileSizeHigh) shl 32);

which works on my 32 bit operating system, but does not work on Vista 64 bit!

Finally,

FileSize := Info.nFileSizeHigh;
FileSize := FileSize shl 32;
FileSize := Info.nFileSizeLow or FileSize;

works on both systems.

Can someone explain the differences in these three versions?

like image 897
jpfollenius Avatar asked Feb 25 '23 03:02

jpfollenius


1 Answers

Generally speaking, the type of the expression a * b, where a and b are of type Integer and * is an operator that applies to Integer, is an integer type with the same range as Integer. (I say generally, as an exception is /.) In order for an operator to use 64-bit operations, one or more of the operands must have a range that is only expressible with a 64-bit type. That should cause all the operands to be promoted to 64-bit, and a 64-bit operation performed.

The fact that the left hand side of an assignment is a 64-bit location generally has no effect on the interpretation and typing of the expression on the right hand side of the assignment operator. This is the way it is in almost all languages that I'm aware of that have statically dispatched 32-bit and 64-bit operator overloads (as opposed to polymorphically dispatched operators on arbitrary precision integers or numeric towers etc.); making things behave otherwise would be very surprising behaviour.

For example, arguments to procedure calls are effectively implicit assignments to the parameters. If the left hand side of an assignment could change the interpretation of the expression on the right, we would not know how to interpret the argument to a procedure call without already knowing the definition:

var a, b: Integer;
// ...
P((a shl 16) or b); // 32-bit operation or 64-bit operation?

I do not know why you are seeing different behaviour with your second and third versions of the code. As far as I can see, they should be interpreted the same, and in my tests, they are interpreted the same. If you could provide sample code that works on 32-bit Windows but fails on 64-bit Windows, I could investigate further.

like image 105
Barry Kelly Avatar answered Feb 27 '23 17:02

Barry Kelly