http://www.perlmonks.org?node_id=1179502

holandes777 has asked for the wisdom of the Perl Monks concerning the following question:

A hex charater is a hex character or is it?

A) my $indata = ''; B) while ((my $c = $Tty->read(1)) ne "") { $indata .= ($c); } # here + I am bringing in hex chracters one at a time. The unit sends me 0xfc + 0x05 0x11 0x27 and 0x56 C) my $payload = extract_payload($indata); # this syas we have 5 byte +s total, we strip to the length and strip the 2 byte CRC at the end l +eaving 0x11 D) my $prtpayload = unpack "H*", $payload; my $prtstatus = unpack "H*" +, substr($payload,0,1); print "kk: payload=$prtpayload status=$prtsta +tus "; E) my $status = substr($payload,0,1); # in this case it is the only b +yte F) $prtstatus = unpack "H*", $status; my $ordstatus = ord($status); pr +int "kk: status2=$prtstatus status3=$ordstatus "; G) if ( $status eq 0x11 ) { print "ok_0x11 "; } else { print "not_0x11 + "; } # note that I also used == for the comparison "just in case) a +nd had the same results OUTPUT: kk: payload=11 status=11 kk: status2=11 status3=17 not_0x11

here is where I am massively confused:

1) I know, for a fact, from the protocol manual and the channel analyzer, that the unit is sending 0x11

2) The output generated by D and F both indicate it is 0x11 or 17 decimal.

3) Why does "G" say that $status, which is 0x11 is not 0x11?

Thanks you all!

Replies are listed 'Best First'.
Re: vexed by the hex!
by Eily (Monsignor) on Jan 13, 2017 at 14:07 UTC

    The eq operator works on strings, and thus turns its two operands into strings before doing anything else. This is called "string context" and also happen when you print something:

    # here EXPR is in string context print EXPR;
    0x11 is a number (17), not a string, so perl turns it into a string the way it usually does. You can try this: print 0x11; and you'll see that ($status eq 0x11) is actually ($status eq "17"). If you want to do a character comparison, you can do: $status eq chr(17)

Re: vexed by the hex!
by choroba (Cardinal) on Jan 13, 2017 at 14:10 UTC
    perl -wE 'say 0x11 eq "\x11"'

    Of course not.

    perl -wE 'say chr 17 eq "\x11"' 1

    ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,
Re: vexed by the hex!
by Anonymous Monk on Jan 13, 2017 at 19:09 UTC
    This seems to be a common stumbling block for C programmers. C has a "character" data type (several, actually) that is really an int in disguise. Perl does not. The automatic int-to-char conversions that happen in C do not happen in Perl.

      so my understanding is:need to use ord() operator to convert it to something I want: if (ord($whatever) == 0x11), correct?

      Thanks much!

        ... if (ord($whatever) == 0x11), correct?

        Correct! (Although other solutions are, of course, possible.)


        Give a man a fish:  <%-{-{-{-<