zoukankan      html  css  js  c++  java
  • php的常量

    之前一直没看过php中是如何定义一个常量的,今天空闲的时候看了下,发现其机制也很简单

    在php中定义常量 有define,和const两个方法

    区别是define是个函数

    const是个结构

    define不能用于类中

    可以用define 定义一个表达式,

    const不能定义为一个表达式

    <?php
    const ABC="def";
    echo ABC;
    ?>

    const ABC="def"对应的opcode为 ZEND_DECLARE_CONST ,其实常说的opcode是zend_op这个结构体里的一个属性,叫opcode, 就是一个数字,只不过以宏的形式展现

    static int ZEND_FASTCALL  ZEND_DECLARE_CONST_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
    {
        USE_OPLINE
    
        zval *name;
        zval *val;
        zend_constant c;
    
        SAVE_OPLINE();
        name  = opline->op1.zv;
        val   = opline->op2.zv;
    
        if ((Z_TYPE_P(val) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT || Z_TYPE_P(val) == IS_CONSTANT_ARRAY) {
            ///
        } else {
            INIT_PZVAL_COPY(&c.value, val);
            zval_copy_ctor(&c.value);
        }
        c.flags = CONST_CS; /* non persistent, case sensetive */
        c.name = IS_INTERNED(Z_STRVAL_P(name)) ? Z_STRVAL_P(name) : zend_strndup(Z_STRVAL_P(name), Z_STRLEN_P(name));
        c.name_len = Z_STRLEN_P(name)+1;
        c.module_number = PHP_USER_CONSTANT;
    
        if (zend_register_constant(&c TSRMLS_CC) == FAILURE) {
        }
    
        CHECK_EXCEPTION();
        ZEND_VM_NEXT_OPCODE();
    }

    最终放到的是EG(zend_constant)这个hashtable里

    ZEND_API int zend_register_constant(zend_constant *c TSRMLS_DC)
    {
        char *lowercase_name = NULL;
        char *name;
        int ret = SUCCESS;
        ulong chash = 0;
    
    
        if (!(c->flags & CONST_CS)) {
            /* keep in mind that c->name_len already contains the '' */
            lowercase_name = estrndup(c->name, c->name_len-1);
            zend_str_tolower(lowercase_name, c->name_len-1);
            lowercase_name = (char*)zend_new_interned_string(lowercase_name, c->name_len, 1 TSRMLS_CC);
            name = lowercase_name;
            chash = IS_INTERNED(lowercase_name) ? INTERNED_HASH(lowercase_name) : 0;
        } else {
            
        }
        if (chash == 0) {
            chash = zend_hash_func(name, c->name_len);
        }
    
        /* Check if the user is trying to define the internal pseudo constant name __COMPILER_HALT_OFFSET__ */
        if ((c->name_len == sizeof("__COMPILER_HALT_OFFSET__")
            && !memcmp(name, "__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__")-1))
            || zend_hash_quick_add(EG(zend_constants), name, c->name_len, chash, (void *) c, sizeof(zend_constant), NULL)==FAILURE) {
            
            ///
            ret = FAILURE;
        }
        if (lowercase_name && !IS_INTERNED(lowercase_name)) {
            efree(lowercase_name);
        }
        return ret;
    }

    echo ABC的时候, opcode是ZEND_FETCH_CONSTANT,下面的函数会把取出的数据赋值给  zend_op中的属性result, echo 时,再显示这个result的值

    static int ZEND_FASTCALL  ZEND_FETCH_CONSTANT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
    {
        USE_OPLINE
    
        SAVE_OPLINE();
        if (IS_UNUSED == IS_UNUSED) {
            zend_constant *c;
            zval *retval;
    
            if (CACHED_PTR(opline->op2.literal->cache_slot)) {
                c = CACHED_PTR(opline->op2.literal->cache_slot);
            } else if ((c = zend_quick_get_constant(opline->op2.literal + 1, opline->extended_value TSRMLS_CC)) == NULL) {
                if ((opline->extended_value & IS_CONSTANT_UNQUALIFIED) != 0) {
                    char *actual = (char *)zend_memrchr(Z_STRVAL_P(opline->op2.zv), '\', Z_STRLEN_P(opline->op2.zv));
                    if(!actual) {
                        actual = Z_STRVAL_P(opline->op2.zv);
                    } else {
                        actual++;
                    }
                    /* non-qualified constant - allow text substitution */
                    zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", actual, actual);
                    ZVAL_STRINGL(&EX_T(opline->result.var).tmp_var, actual, Z_STRLEN_P(opline->op2.zv)-(actual - Z_STRVAL_P(opline->op2.zv)), 1);
                    CHECK_EXCEPTION();
                    ZEND_VM_NEXT_OPCODE();
                } else {
                    zend_error_noreturn(E_ERROR, "Undefined constant '%s'", Z_STRVAL_P(opline->op2.zv));
                }
            } else {
                CACHE_PTR(opline->op2.literal->cache_slot, c);
            }
            retval = &EX_T(opline->result.var).tmp_var;
            ZVAL_COPY_VALUE(retval, &c->value);
            zval_copy_ctor(retval);
            CHECK_EXCEPTION();
            ZEND_VM_NEXT_OPCODE();
        }
    }
  • 相关阅读:
    【BZOJ】2019: [Usaco2009 Nov]找工作(spfa)
    【BZOJ】3668: [Noi2014]起床困难综合症(暴力)
    Redis 字符串结构和常用命令
    Redis实现存取数据+数据存取
    Spring 使用RedisTemplate操作Redis
    使用 java替换web项目的web.xml
    SQL server 从创建数据库到查询数据的简单操作
    SQL server 安装教程
    IntelliJ IDEA 注册码(因为之前的地址被封杀了,所以换了个地址)
    对程序员有帮助的几个非技术实用链接(点我,你不会后悔的)
  • 原文地址:https://www.cnblogs.com/taek/p/6700892.html
Copyright © 2011-2022 走看看