1

I have a Delphi-7 expression as below, all variables are of type longint-

cy:=((s1 and s2)or((s1 or s2)and not res))shr 31;

And in C# the expression is, all variables are of type int-

cy = ((s1 & s2) | ((s1 | s2) & (~res)))>>31;

where

s1  = -659459908
s2  =  283372503 
res =  217426595

When Delphi 7 evaluates it, and I look the value of expression to the right by quick watch it shows value as -1, but when I ShowMessage(IntToStr(cy)), it shows 1.

Whereas C# still shows -1.

I am working on Windows-10 64 bit system and compiling the code for Any CPU from VS2013. I tried declaring the C# variables as Int32 as well, but same phenomenon occurs.

Can anyone tell about this phenomenon, what we say this and how to proceed further.

Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215
Prateek Shukla
  • 593
  • 2
  • 7
  • 27
  • Mistakenly written. question is updated. All variable in delphi are of type longint. where as in C# all are type of int. – Prateek Shukla Nov 03 '17 at 12:58
  • In Delphi `shr` is logical shift. In C# `>>` is arithmetic shift. Which do you want? https://en.wikipedia.org/wiki/Bitwise_operation#Bit_shifts – David Heffernan Nov 03 '17 at 13:01
  • Well, clearly C# and Delphi is different. Pick one and implement the other differently. – Lasse V. Karlsen Nov 03 '17 at 13:01
  • Yes it is coming as negative by all C#, Delphi-7 and calculator. but ShowMessage is showing it as '1'. – Prateek Shukla Nov 03 '17 at 13:02
  • The C# documentation states _If the first operand is an int or long, the right-shift is an arithmetic shift (high-order empty bits are set to the sign bit)._ The Delphi documentation states that it does NOT preserve the sign bit: http://docwiki.embarcadero.com/RADStudio/Tokyo/en/Expressions_(Delphi) – Günther the Beautiful Nov 03 '17 at 13:02
  • Does `cy` in Delphi contain -1 or 1 before that ShowMessage? – Lasse V. Karlsen Nov 03 '17 at 13:02
  • @LasseVågsætherKarlsen Delphi evaluates expression ((s1 and s2)or((s1 or s2)and not res))shr 31 as -1 but assigns 1 to cy. – Prateek Shukla Nov 03 '17 at 13:11
  • What you mean is that the debugger is evaluating in a different way compared to the compiled code. That sounds about right as an observation for Delphi 7, there's plenty of such mismatches. (those are bugs in in the Delphi debugger, make no mistake) – Lasse V. Karlsen Nov 03 '17 at 13:19
  • @Prateek Yes, that's a debugger defect. Don't trust it. You still haven't told us whether you want arithmetic or logic shift. Do you know? – David Heffernan Nov 03 '17 at 13:44
  • We are performing bitwise operation(arithmetic shift). – Prateek Shukla Nov 03 '17 at 13:53
  • So you are happy with the C# code and want to implement arithmetic shift in Delphi? – David Heffernan Nov 03 '17 at 14:16
  • Why bitshift at all? It's an unneccesarily obfuscated way to check if the number is negative or not. – J... Nov 03 '17 at 19:10

1 Answers1

7

In C# >> operation preserves the leftmost bit when opertaing with signed integers like int, long (alas C# doesn't have any >>> operation as in Java), when Delphi's shr doesn't:

In both cases (C# and Delphi) we have the same evaluation for the inner formula

// -79459485 (decimal) == 11010000101000110111000111011100 (binary) 
((s1 & s2) | ((s1 | s2) & (~res))) == -794594852 

The final step (-794594852 >> 31 and -794594852 shr 31) is different:

11010000101000110111000111011100 >> 31 == 11111111111111111111111111111111 (C#)
11010000101000110111000111011100 >> 31 == 00000000000000000000000000000001 (Delphi)

Amendment (let C# mimic Delphi):

 unchecked { 
   cy = (int)((uint)((s1 & s2) | ((s1 | s2) & (~res))) >> 31);
 }
HeartWare
  • 7,464
  • 2
  • 26
  • 30
Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215