Search code examples
perlxs

How to store null in Perl hash


I want to use Perl hash in my C code (XS) as a set, so I only need to keep keys in hash. Is it possible to store something like null or another constant value to avoid creating unnecessary value?

Something like this:

int add_value(HV *hash, SV *value)
{
    // just an example of key
    char key[64];
    sprintf(key, "%p", value);
    if (hv_exists(hash, key, strlen(key)) return 0;

    // here I need something instead of ?
    return hv_stores(hash, key, ?) != NULL;
}

One of possible solution could be to store value itself, but maybe there is special constant for undef or null.


Solution

  • &PL_sv_undef is the undef scalar. It's read-only. You probably want a fresh undef scalar, as created using newSV(0)[1].

    The scalar returned by newSV(0) starts with a refcount of one, of which the hash "takes possession" when the scalar is stored in it using hv_stores, so don't SvREFCNT_dec or sv_2mortal the returned scalar. (Do increase the reference count if you store it elsewhere too.)


    1. # "The" undef (A specific read-only variable that will never get deallocated)
      $ perl -MDevel::Peek -e'Dump(undef)'
      SV = NULL(0x0) at 0x3596700
        REFCNT = 2147483641
        FLAGS = (READONLY,PROTECT)
      
      # "An" undef (It's not the type of SVt_NULL that make it undef...)
      $ perl -MDevel::Peek -e'Dump($x)'
      SV = NULL(0x0) at 0x1bb7880
        REFCNT = 1
        FLAGS = ()
      
      # Another undef (... It's the lack of "OK" flags that make it undef)
      $ perl -MDevel::Peek -e'$x="abc"; $x=undef; Dump($x)'
      SV = PV(0x3d5f360) at 0x3d86590
        REFCNT = 1
        FLAGS = ()
        PV = 0