سؤال

When looking at the Perl API, I was wondering why

  • sv_setref_iv() stores its IV argument in the IV slot,
  • sv_setref_nv() stores its NV argument in the NV slot,
  • but sv_setref_pv() stores its void * argument in the IV slot, instead of the PV slot?

I have a hunch (the CUR and LEN fields wouldn't make sense for such a variable), but I'd like to have the opinion of someone knowledgeable in XS :-)

هل كانت مفيدة؟

المحلول

There are many different types of scalars.

  • SvNULL isn't capable of holding any value except undef.
  • SvIV is capable of holding an IV, UV or RV.
  • SvNV is capable of holding an NV.
  • SvPV is capable of holding a PV.
  • SvPVIV is capable of holding a PV, as well as an IV, UV or RV.
  • ...

AV, HV, CV, GV are really just types of scalar too.

Note I said "capable" of holding. You can think of scalars as being objects, and the above as being classes and subclasses. Each of the above has a different structure.

Having these different types of scalars allows one to save memory.

An SvIV (the smallest scalar type capable of holding an IV) is smaller than an SvPV (the smallest scalar type capable of holding a PV).

$ perl -le'
   use Devel::Size qw( total_size );

   use Inline C => <<'\''__EOI__'\'';

      void upgrade_to_iv(SV* sv) {
         SvUPGRADE(sv, SVt_IV);
      }

      void upgrade_to_pv(SV* sv) {
         SvUPGRADE(sv, SVt_PV);
      }

__EOI__

   { my $x; upgrade_to_iv($x); print total_size($x); }
   { my $x; upgrade_to_pv($x); print total_size($x); }
'
24
40

Using an SvIV instead of an SvPV is a savings of 16 bytes per reference.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top