1

I am converting a working C++ program to php. Now even though most of the program works I am having trouble with one aspect of it.

The code that works in C++ is not giving the same results in php. This is for writing to a binary file later in my code.

Here is the C++ code and the result.

C++
char test;
test = 16;
test+=(char)131;
std::cout << (int)test << endl;
Result = -109

and here is the equivalent code in php.

PHP
$test = chr(0);
$test = 16;
$test+= chr(131);
echo (int)$test;
Result = 16

I am guessing this might have something to do with unicode encoding giving me the wrong result. The result should be -109 as my C++ program works correctly, but I am not getting the same result in php.

When I cout (int)(char)131 in C++ I get -125, but if I echo chr(131) in php I get 0;

Is there anyway to make my php output the same as my C++?

Thomas Williams
  • 1,528
  • 1
  • 18
  • 37
  • 4
    If you have code like that in C++, then your program is bad enough that you should try to rewrite the PHP solution from scratch rather than as a faithful translation from C++. – Some programmer dude Oct 23 '19 at 11:15
  • Is the possible overflow an undefined behaviour in c++? – BiagioF Oct 23 '19 at 11:16
  • And remember, in C++ it's implementation specific if `char` is signed or unsigned. If it happens to be unsigned, then your code will not work as you expect. – Some programmer dude Oct 23 '19 at 11:17
  • This isn't my actual code, but a cut down example to show the problem. The c++ program works and is designed to write a binary tajima dst file. It works perfectly, but I need to do the same thing in php, for reasons, but I am not getting the same results. The bit of code I have shown here is intended to set a flag, which is the third byte I am writing to my binary file. Although the format of file doesn't matter here as I am just asking a single question. – Thomas Williams Oct 23 '19 at 11:19
  • 2
    As far as I know this is undefined behavior in C++. The result of signed overflow is undefined. If it works as expected you are lucky but the behavior could change on the next run. https://stackoverflow.com/questions/16188263/is-signed-integer-overflow-still-undefined-behavior-in-c – Thomas Sablik Oct 23 '19 at 11:21
  • I have used the c++ code on multiple DST files and it always works, so I know my C++ code is working correctly. Also please check out the Embroidermodder source code where similar variables are being used http://embroidermodder.sourceforge.net/src/dst.cpp look under encode_record – Thomas Williams Oct 23 '19 at 11:23
  • @BiagioFesta unsigned overflow is well defined, though `char` can be signed or unsigned – 463035818_is_not_an_ai Oct 23 '19 at 11:29
  • 2
    Just because it seems to work for just your situation, with a specific compiler building with a specific set of optimization and for a specific target doesn't mean it will work for all compilers, all optimizations and all targets. UB is tricky that way. – Some programmer dude Oct 23 '19 at 11:30
  • Please look at the link I posted under encode_record and look at the switch flags. This is what I am trying to do in php. This is the official source code of embroider modder, which I based my original code off for converting DSTs to svgs – Thomas Williams Oct 23 '19 at 11:32
  • unsigned overflow is well defined. If signed overflow is used in the link you shouldn't base your programming on this example. – Thomas Sablik Oct 23 '19 at 11:34
  • @formerlyknownas_463035818 Indeed, I wrote "the *possible* overflow". – BiagioF Oct 23 '19 at 11:36
  • I'm sorry, but the code you link to isn't what most people would consider good. Why do e.g. `b2=(char)243` in the first place, instead of assigning the wanted value to begin with (i.e. `b2 = -13`)? It seems the creator of that code reversed-engineered some file format, without bothering to write good code. – Some programmer dude Oct 23 '19 at 11:41
  • 1
    PHP converts e.g. `12 + "12"` to `12 + 12`. Your statement `$test+= chr(131);` is equivalent to `$test = 16 + chr(131)`. `chr(131)` can't be converted to a number so the result is `16`. – Thomas Sablik Oct 23 '19 at 11:43
  • Which is why in my code I changed that line to $b2=chr(-13); ages ago. I am not copying the code exactly, but it does work. There is updated versions of this code. Regardless I am trying to replicate it in php. – Thomas Williams Oct 23 '19 at 11:44
  • It seems you want something like `function pseudo_chr($x) { return $x < 128 : $x : (-256 + $x); }` – Nick Oct 23 '19 at 11:48

2 Answers2

3

You can achieve this with:

<?php
    $test = 16;
    $test = ($test + 131) % 256;
    if ($test > 127) {
        $test -= 256;
    }
    echo $test;
?>

The addition

$test+= chr(131);

doesn't do what you expect. PHP tries to convert the string/character chr(131) into number. It can't convert it because the string doesn't contain any digits so the statement is equivalent to

$test+= 0;
Thomas Sablik
  • 16,127
  • 7
  • 34
  • 62
0

I think the clean way is the c++ expression (int)(char)131 first to correctly convert to PHP integer and then adding the values. The conversion realizes the function signByteToInt():

<?php
function signByteToInt($byteVal){
  $byteVal &= 0xff;
  if($byteVal & 0x80) $byteVal -= 0x100;
  return $byteVal;
}

Example of use

$test = signByteToInt(16);  //16
$add = signByteToInt(131);  //-125

echo $test+$add;  //-109
jspit
  • 7,276
  • 1
  • 9
  • 17