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

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

Hello Monks,

I have a strange problem (may not be so strange for many of you - that is why I post it here!!) I have a CGI script that, picks the value of $bu based on the value of $j as per the logic below (checking for which bit is set in the number $j)

I run the code with $j = 65. That should give the value D. But, somehow, I find that the bitwise & returns true for all the values! Hence the end result is not good.

my %bj = (64,'D', 128,'A', 256,'H'); foreach my $flag (keys %bj) { $bu = $bj{$flag} if ($flag & $job_type); cluck("business_unit: $bu); }

I tried running this code standalone, in a separate pl script and it works good. But somehow it does not work in the CGI(?)

Are there some CGI/run options that could disable the bitwise & ? Tried to google around, but did not find anything useful.

Can you please help me with this?

Replies are listed 'Best First'.
Re: Bitwise & not working correctly in CGI script
by Jenda (Abbot) on Jun 13, 2012 at 15:35 UTC
    print "19 & 16 = ", (19 & 16), "\n"; print "'19' & '16' = ", ('19' & '16'), "\n"; print "'19' & 16 = ", ('19' & 16), "\n"; print "19 & '16' = ", (19 & '16'), "\n";

    The thing is that Perl did not convert the string (keys of a hash are ALWAYS strings, even if you used numeric literals when filling it in.) to a number and instead it evaluated a bitwise AND on the characters of the strings.

    Jenda
    Enoch was right!
    Enjoy the last years of Rome.

      What Jenda is trying to say, what perlnumber (and kennethk ) say, is that you should numify one of your arguments, so write

      #~ if( 0+$flag & $job_type ){ #~ if( $flag & 0+$job_type ){ #~ if( 0+$flag & 0+$job_type ){ if( int $flag & int $job_type ){ $bu = $bj{$flag} ; cluck("business_unit: $bu"); }
      Wow! That was right! The problem got solved when I numified both operands of & by adding 0. Thanks for your help!!
Re: Bitwise & not working correctly in CGI script
by kennethk (Abbot) on Jun 13, 2012 at 15:30 UTC
    I cannot not recover your issue. If I run the code provided (after adding use Carp 'cluck';, my $job_type = 65;, and a closing quote on your line 4, I get the output on STDERR:
    business_unit: at fluff.pl line 7 business_unit: D at fluff.pl line 7 business_unit: D at fluff.pl line 7
    I suspect your issue is that what you actually mean to have is something like
    use strict; use Carp 'cluck'; my $job_type = 65; my %bj = (64,'D', 128,'A', 256,'H'); foreach my $flag (keys %bj) { if ($flag & $job_type) { my $bu = $bj{$flag}; cluck("business_unit: $bu"); } }

    The difference here is that I am now only outputting when the if condition is true; your if applied only to the assignment, not the cluck.

    Update: Jenda also has a plausible explanation, if Re: Bitwise & not working correctly in CGI script is correct. This makes sense if you are pulling the string out of $cgi->param, which contains only strings. You can numify the result using my $job_type = 0+ $cgi->param('job');, for whatever those variables are called locally.


    #11929 First ask yourself `How would I do this without a computer?' Then have the computer do it the same way.

Re: Bitwise & not working correctly in CGI script
by muba (Priest) on Jun 13, 2012 at 15:24 UTC

    It depends on the value of $job_type, I guess. It works fine for me (see below)

    Addendum: Are you sure the value of $job_type is what you think it is?

    #!perl use strict; use warnings; print "Content-Type: text/html\n\n"; print "<html><body>\n"; my @jobtypes = (32, 64, 64|128, 128|256, 64|256); for my $j (@jobtypes) { setBu($j); } print "</body></html>"; sub setBu { my $job_type = shift; my %bj = (64,'D', 128,'A', 256,'H'); print "<ul><li>Job type is $job_type:<ul>\n"; foreach my $flag (keys %bj) { my $bu = $bj{$flag} if ($flag & $job_type); # <solegaonkar> But, somehow, I find that the bitwise & return +s # true for all the values! Hence the end result is not good. # -- Does it? if ($bu) { print " <li>Bu is true for flag $flag</li>\n"; } else { print " <li>Bu is false for flag $flag</li>\n"; } } print "</ul></li></ul>\n\n"; }

    • Job type is 32:
      • Bu is false for flag 128
      • Bu is false for flag 64
      • Bu is false for flag 256
    • Job type is 64:
      • Bu is false for flag 128
      • Bu is true for flag 64
      • Bu is false for flag 256
    • Job type is 192:
      • Bu is true for flag 128
      • Bu is true for flag 64
      • Bu is false for flag 256
    • Job type is 384:
      • Bu is true for flag 128
      • Bu is false for flag 64
      • Bu is true for flag 256
    • Job type is 320:
      • Bu is false for flag 128
      • Bu is true for flag 64
      • Bu is true for flag 256