• php 常量


    常量存储位置

    1 EG(zend_constants)

    常量的内部结构
    在Zend/zend_constants.h文件的33行可以看到如下所示的结构定义。在常量的结构中,除了与变量一样的zval结构,它还包括属于常量的标记,常量名以及常量所在的模块号

    typedef struct _zend_constant {
      zval value;/* zval结构,PHP内部变量的存储结构,在第一小节有说明 */
      int flags; /* 常量的标记如 CONST_PERSISTENT | CONST_CS |CONST_CT_SUBST */
      char *name;/* 常量名称 */
      uint name_len;
      int module_number;/* 模块号 */ 
    } zend_constant;

    flags取值:
    CONST_PERSISTENT:表示这个常量需要持久化。这里的持久化内存申请时的持久化是一个概念,非持久常量会在请求结束时释放该常量。如果是非持久常量,会在RSHUTDOWN阶段就将该常量释放,否则只会在MSHUTDOWN阶段将内存释放,在用户空间,也就是用户定义的常量都是非持久化的,通常扩展和内核定义的常量会设置为持久化,因为如果常量被释放了,而下次请求又需要使用这个常量,该常量就必须在请求时初始化一次,而对于常量这些不变的量来说就是个没有意义的重复计算。

    CONST_CT_SUBST: /* Allow compile-time substitution */(在编译时可被替换)。

    CONST_CS: /* Case Sensitive */ 大小写敏感

    define函数的实现
    define是PHP的内置函数,在Zend/zend_builtin_functions.c文件中定义了此函数的实现

    /* {{{ proto bool define(string constant_name, mixed value, boolean case_insensitive=false)
       Define a new constant */
    ZEND_FUNCTION(define)
    {
        char *name;
        int name_len;
        zval *val;
        zval *val_free = NULL;
        zend_bool non_cs = 0;
        int case_sensitive = CONST_CS; //  是否大小写敏感,默认为1
        zend_constant c;
    
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|b", &name, &name_len, &val, &non_cs) == FAILURE) {
            return;
        }
    
        if(non_cs) {
            case_sensitive = 0;
        }
    
        /* class constant, check if there is name and make sure class is valid & exists */
        if (zend_memnstr(name, "::", sizeof("::") - 1, name + name_len)) {
            zend_error(E_WARNING, "Class constants cannot be defined or redefined");
            RETURN_FALSE;
        }
    
    repeat:
        switch (Z_TYPE_P(val)) {
            case IS_LONG:
            case IS_DOUBLE:
            case IS_STRING:
            case IS_BOOL:
            case IS_RESOURCE:
            case IS_NULL:
                break;
            case IS_OBJECT:
                if (!val_free) {
                    if (Z_OBJ_HT_P(val)->get) {
                        val_free = val = Z_OBJ_HT_P(val)->get(val TSRMLS_CC);
                        goto repeat;
                    } else if (Z_OBJ_HT_P(val)->cast_object) {
                        ALLOC_INIT_ZVAL(val_free);
                        if (Z_OBJ_HT_P(val)->cast_object(val, val_free, IS_STRING TSRMLS_CC) == SUCCESS) {
                            val = val_free;
                            break;
                        }
                    }
                }
                /* no break */
            default:
                zend_error(E_WARNING,"Constants may only evaluate to scalar values");
                if (val_free) {
                    zval_ptr_dtor(&val_free);
                }
                RETURN_FALSE;
        }
        
        c.value = *val;
        zval_copy_ctor(&c.value);
        if (val_free) {
            zval_ptr_dtor(&val_free);
        }
        c.flags = case_sensitive; /* non persistent */
        c.name = zend_strndup(name, name_len);
        c.name_len = name_len+1;
        c.module_number = PHP_USER_CONSTANT;
        if (zend_register_constant(&c TSRMLS_CC) == SUCCESS) {
            RETURN_TRUE;
        } else {
            RETURN_FALSE;
        }
    }
    /* }}} */

    其实现上是一个将传递的参数传递给新建的zend_constant结构,并将这个结构体注册到常量列表中的过程。

    例子:标准常量TRUE的定义

    /*声明结构体*/
    zend_constant c;
    /*结构体赋值*/
    c.flags = CONST_PERSISTENT | CONST_CT_SUBST;
    c.module_number = 0;
    c.name = zend_strndup(ZEND_STRL("TRUE"));
    c.name_len = sizeof("TRUE");
    c.value.value.lval = 1;
    c.value.type = IS_BOOL;
    /*注册结构体*/
    zend_register_constant(&c TSRMLS_CC);

    常量的销毁

    非持久化常量在request请求结束时销毁,具体销毁操作在:php_request_shutdown()->zend_deactivate()->shutdown_executor()->clean_non_persistent_constants()。

    1 void clean_non_persistent_constants(TSRMLS_D)
    2 {
    3     if (EG(full_tables_cleanup)) {
    4         zend_hash_apply(EG(zend_constants), (apply_func_t) clean_non_persistent_constant_full TSRMLS_CC);
    5     } else {
    6         zend_hash_reverse_apply(EG(zend_constants), (apply_func_t) clean_non_persistent_constant TSRMLS_CC);
    7     }
    8 }
    for remember
  • 相关阅读:
    软件体系结构:二维分层、模块化和开放平台
    Unity手游之路<七>角色控制器
    Unity手游之路<四>3d旋转-四元数,欧拉角和变幻矩阵
    Unity手游之路<三> 基于Unity+Java的聊天室源码
    Unity手游之路<二>Java版服务端使用protostuff简化protobuf开发
    Unity手游之路<一>C#版本Protobuf
    Unity手游之路<八>自动寻路Navmesh之入门
    Unity手游之路<九>自动寻路Navmesh之高级主题
    Unity手游之路<十>自动寻路Navmesh之跳跃,攀爬,斜坡
    raise EnvironmentError("%s not found" % (mysql_config.path,)) EnvironmentError: mysql_config not found 解决办法
  • 原文地址:https://www.cnblogs.com/dearmrli/p/9438299.html
Copyright © 2020-2023  润新知