luaの怪しげな

2965 ワード

luaの#はtableの秩序化シーケンスを取得する個数である.例:
local t = {a = 1, 1,3,4,5,6}
print(#t)--5

tableの実装では、要素、配列、hashハッシュの2つの方法で要素を保存します.tableの配列要素の個数を取得します.たとえば、上のコードは配列を取得する個数です.ここで、a=1はハッシュ・リストに保存されます.tableにnilをいくつ増やしたら、何か問題がありますか?
local t = {a = 1, 1,3,nil,4,5,6,nil}
print(#t)--2
はかなり怪しいのではないでしょうか.どうしてこんなことになったの?私たちはソースコードから一歩一歩霧を剥がした.
const TValue *luaH_getint (Table *t, lua_Integer key) {
  /* (1 <= key && key <= t->sizearray) */
  if (l_castS2U(key) - 1 < t->sizearray)
    return &t->array[key - 1];
  else {
    Node *n = hashint(t, key);
    for (;;) {  /* check whether 'key' is somewhere in the chain */
      if (ttisinteger(gkey(n)) && ivalue(gkey(n)) == key)
        return gval(n);  /* that's it */
      else {
        int nx = gnext(n);
        if (nx == 0) break;
        n += nx;
      }
    }
    return luaO_nilobject;
  }
}
static int unbound_search (Table *t, unsigned int j) {
  unsigned int i = j;  /* i is zero or a present index */
  j++;
  /* find 'i' and 'j' such that i is present and j is not */
  while (!ttisnil(luaH_getint(t, j))) {//             nil,
    i = j;
    if (j > cast(unsigned int, MAX_INT)/2) {  /*    ,  j > MAX_INT/2     。  table     table */
      /* table was built with bad purposes: resort to linear search */
      i = 1;
      while (!ttisnil(luaH_getint(t, i))) i++;//        nil,     。
      return i - 1;
    }
    j *= 2;
  }
  /*        。     while   ,i = j, j =    2 。m = (i + j)/2        m = (j + 2j)/2,        ,m = j + floor(j/2),  m > j(  table    ),ttisnil   nil,j = m.        ,  i= j ,   m = (j + floor(j/2) + j)/2     m = j + floor(j/4),    table     ,ttisnil   nil,j = m。         ,m         */
while (j - i > 1) {
    unsigned int m = (i+j)/2;
    if (ttisnil(luaH_getint(t, m))) j = m;
    else i = m;
  }
  return i;
}
int luaH_getn (Table *t) {
  unsigned int j = t->sizearray;//  table         
  if (j > 0 && ttisnil(&t->array[j - 1])) {//      0         nil,          。*  lua         。
    /* there is a boundary in the array part: (binary) search for it */
    unsigned int i = 0;
    while (j - i > 1) {
      unsigned int m = (i+j)/2;//      
      if (ttisnil(&t->array[m - 1])) j = m;
      else i = m;
    }
    return i;
  }
  /* else must find a boundary in hash part */
  else if (isdummy(t->node))  /*   hash   ,          */
    return j;  /* that is easy... */
  else return unbound_search(t, j);/*    */
}

, table nil , m, m-1 nil 。