第一版是针对 Lua 5.0 编写的。虽然在很大程度上仍然适用于更高版本,但还是有一些区别。
第四版针对 Lua 5.3,可在 亚马逊 和其他书店购买。
购买本书,您还可以帮助 支持 Lua 项目


24.2.3 – 其他堆栈操作

除了上述函数(在 C 和堆栈之间交换值)之外,API 还提供以下操作用于通用堆栈操作

    int   lua_gettop (lua_State *L);
    void  lua_settop (lua_State *L, int index);
    void  lua_pushvalue (lua_State *L, int index);
    void  lua_remove (lua_State *L, int index);
    void  lua_insert (lua_State *L, int index);
    void  lua_replace (lua_State *L, int index);
lua_gettop 函数返回堆栈中的元素数量,这也是顶部元素的索引。请注意,负索引 -x 等于正索引 gettop - x + 1

lua_settop 将顶部(即堆栈中的元素数量)设置为特定值。如果之前的顶部高于新的顶部,则会丢弃顶部值。否则,该函数会在堆栈上压入 nil,以获得给定的大小。作为特殊情况,lua_settop(L, 0) 会清空堆栈。您还可以对 lua_settop 使用负索引;这会将顶部元素设置为给定的索引。使用此功能,API 提供以下宏,该宏从堆栈中弹出 n 个元素

    #define lua_pop(L,n)  lua_settop(L, -(n)-1)

lua_pushvalue 函数在堆栈顶部压入给定索引处元素的副本;lua_remove 删除给定索引处的元素,将该位置上方的所有元素向下移动以填补空缺;lua_insert 将顶部元素移动到给定位置,将该位置上方的所有元素向上移动以腾出空间;最后,lua_replace 从顶部弹出值并将其设置为给定索引的值,而不移动任何内容。请注意,以下操作对堆栈没有影响

    lua_settop(L, -1);  /* set top to its current value */
    lua_insert(L, -1);  /* move top element to the top */

为了说明这些函数的使用,这里有一个有用的帮助函数,用于转储堆栈的全部内容

    static void stackDump (lua_State *L) {
      int i;
      int top = lua_gettop(L);
      for (i = 1; i <= top; i++) {  /* repeat for each level */
        int t = lua_type(L, i);
        switch (t) {
    
          case LUA_TSTRING:  /* strings */
            printf("`%s'", lua_tostring(L, i));
            break;
    
          case LUA_TBOOLEAN:  /* booleans */
            printf(lua_toboolean(L, i) ? "true" : "false");
            break;
    
          case LUA_TNUMBER:  /* numbers */
            printf("%g", lua_tonumber(L, i));
            break;
    
          default:  /* other values */
            printf("%s", lua_typename(L, t));
            break;
    
        }
        printf("  ");  /* put a separator */
      }
      printf("\n");  /* end the listing */
    }
此函数从底部到顶部遍历堆栈,根据每个元素的类型打印每个元素。它在引号之间打印字符串;对于数字,它使用 `%g´ 格式;对于其他值(表、函数等),它仅打印其类型(lua_typename 将类型代码转换为类型名称)。

以下程序使用 stackDump 进一步说明 API 堆栈的操作

    #include <stdio.h>
    #include <lua.h>
    
    static void stackDump (lua_State *L) {
      ...
    }
    
    int main (void) {
      lua_State *L = lua_open();
      lua_pushboolean(L, 1); lua_pushnumber(L, 10);
      lua_pushnil(L); lua_pushstring(L, "hello");
      stackDump(L);
                       /* true  10  nil  `hello'  */
    
      lua_pushvalue(L, -4); stackDump(L);
                       /* true  10  nil  `hello'  true  */
    
      lua_replace(L, 3); stackDump(L);
                       /* true  10  true  `hello'  */
    
      lua_settop(L, 6); stackDump(L);
                       /* true  10  true  `hello'  nil  nil  */
    
      lua_remove(L, -3); stackDump(L);
                       /* true  10  true  nil  nil  */
    
      lua_settop(L, -5); stackDump(L);
                       /* true  */
    
      lua_close(L);
      return 0;
    }