Question

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!

Was it helpful?

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top