Search code examples
perlsubroutinecrc

Perl Hex CRC-16 bit script


I'm new to perl and i would like to know why the arguments are not correcly passed to the subroutine. Also, are the output values correct?

use strict;

sub crc16 {
     use constant POLY => $_[1];
     my $crc = 0;
     for my $c ( unpack 'C*', $_[0] ) {
         $crc ^= $c;
         for my $b ( 0 .. 7 ) {
             my $carry = $crc & 1;
             $crc >>= 1;
             if( $carry ) {
                 $crc ^= POLY;
             }
         }
     }
     return $crc;
}

my $data = "1234";
my $poly = "0x8005";

printf "crc: %04x\n", crc16( $data, $poly );

Thanks!


Solution

  • An use ... statement is always executed at compile time, and is not subject to normal control flow. During compile time, the @_ array does not contain elements, so $_[1] will be undefined. You should be using regular variables:

    sub crc16 {
       my ($string, $poly) = @_;
       my $crc = 0;
       for my $c ( unpack 'C*', $string ) {
          $crc ^= $c;
          for ( 0 .. 7 ) {
             my $carry = $crc & 1;
             $crc >>= 1;
             $crc ^= $poly if $carry;
          }
       }
       return $crc;
    }
    

    Oh, and you should be specifying the $poly as an integer, not a string: $poly = 0x8005, without the quotes.


    As I pointed out in a comment on a similar question of yours, there already is a Perl module that implements CRC algorithms: Digest::CRC. The important parts are coded in C for performance. The provided functions are highly parameterizable. I urge you to find a way to use that module instead of reinventing the wheel.