Bitwise operator XOR (^) gives different results in linux and windows
Asked Answered
R

1

7

for some reason long to explain I want to do the following bitwise operations in perl: (let's assume that 1 means true and 0 means false)

$var1="11000001";
$var2="10000101";

$y=$var1 & $var2; #bitwise and
$o=$var1 | $var2; #bitwise or
print "var1 & var2: $y\n";
print "var1 | var2: $o\n";

Then, I get the same output both in windows perl and in Linux perl:

var1 & var2: 10000001 (which is what I wished)
var1 | var2: 11000101 (which is what I wished)

BUT if I do:

$xox=$var1^$var2; # bitwise xor
print "var1 ^ var2: $xox\n";

then the output in windows is:

var1 ^ var2:  ☺   ☺

while in linux is:

var1 ^ var2: 

Given that the & and | operators seem to work as 'expected', I was also expecting to get something like:

$var1="11000001";
$var2="10000101";
$xox=$var1^$var2; # bitwise xor
print "var1 ^ var2 --> $xox\n";

var1 ^ var2 --> 01000100

for the ^ operator.

But, as shown above, this is not the case for both windows and linux, although at least the windows output for xor is useful for my purposes, but not the linux output.

Can anyone explain why the '&' or '|' operators seem to work but not the '^' (XOR) operator? And why is there that difference between linux and windows? Thanks

NOTE: specifying int($var1) ^ int($var2) does not result in a desirable result (for me; i.e. to get as output 01000100)

Redford answered 28/5, 2023 at 14:1 Comment(1)
As for the difference between Win and Linux, is just a difference in how the terminal interprets non-printable control characters. If you were to check what bytes are output, you'll find them to be identical (CRLF vs LF line endings aside).Croesus
O
10

Can anyone explain why the '&' or '|' operators seem to work but not the '^' (XOR) operator?

It's more or less a coincidence that & and | work, based on the character codes of the 0 and 1 characters:

0x30 | 0x31 = 0x31 (observed: "0" | "1" = "1")
0x30 & 0x31 = 0x30 (observed: "0" & "1" = "0")

Both & and | preserve the 3 in the top nibble, and the bottom nibble of the 0 and 1 characters happen to be 0 and 1 respectively.

XOR zeroes out the 3 in the top nibble, so you get some nonsense characters, which are printed differently based on how the OS interprets them. Apparently the character with the value 1 (just 1, not 0x31, normally it's an unprintable character) is shown as ☺ on windows at least in some situations.

As a quick hack, you could do this to put the 3's back in the top nibbles:

$xox=($var1^$var2)|"00000000"; # bitwise xor

I think that's a hack though.

NOTE: specifying int($var1) ^ int($var2) does not result in a desirable result (for me; i.e. to get as output 01000100)

Because you did not specify that these were numbers in binary, they're not being parsed as intended. Here's one way to do it, note that leading zeroes are not preserved this way:

print sprintf("%b", oct("0b$var1") ^ oct("0b$var2"));
Ohalloran answered 28/5, 2023 at 14:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.