变量(Variables)

创建(Creation)

与 PHP 不同,C 中的每个变量必须在我们函数的开头声明,在使用前必须初始化。甚至,当我们改变它的时候,它应该再次被重新初始化,例如:

  1. // Declare the variable and initialize the variable
  2. zval some_number = {};
  3.  
  4. // Assign it a string value
  5. ZVAL_STRING(some_number, "one hundred");
  6.  
  7. // Reinitialize the variable and change its value to long
  8. PHALCON_INIT_NVAR(some_number);
  9. ZVAL_LONG(some_number, 100);

If a variable is assigned within a cycle or it’s re-assigned is important to initialize it to NULL in its declaration.By doing this, PHALCON_INIT_NVAR will know if the variable needs memory or it already have memory allocated.

变量的复制

PHP7 中 提供 ZVAL_COPY_VALUE`ZVAL_COPY与 [](http://www.myleftstudio.com/internals/#id4)ZVAL_DUP`等宏定义来实现变量的复制。

  1. zval a = {}, b = {}, c = {};
  2.  
  3. ZVAL_LONG(&a, 1500);
  4.  
  5. // 复制
  6. ZVAL_COPY_VALUE(&b, &a);
  7.  
  8. // 在 ZVAL_COPY_VALUE 的基础上,复制并增加 a 引用计数,不过对不是 IS_TYPE_REFCOUNTED 的不会增加引用计数
  9. ZVAL_COPY(&b, &a);
  10.  
  11. // 在 ZVAL_COPY_VALUE 的基础上,如果类型是需要引用计数(IS_TYPE_REFCOUNTED)会增加自身引用计数
  12. // 如果是可被复制的(IS_TYPE_COPYABLE)或不可变的(IS_TYPE_IMMUTABLE)的类型,会执行 `zval_copy_ctor_func`
  13. array_init(&c);
  14. ZVAL_DUP(&a, &c);

zval_copy_ctor_func 实现:

  1. ZEND_API void ZEND_FASTCALL _zval_copy_ctor_func(zval *zvalue ZEND_FILE_LINE_DC)
  2. {
  3. if (EXPECTED(Z_TYPE_P(zvalue) == IS_ARRAY)) {
  4. ZVAL_ARR(zvalue, zend_array_dup(Z_ARRVAL_P(zvalue)));
  5. } else if (EXPECTED(Z_TYPE_P(zvalue) == IS_STRING) ||
  6. EXPECTED(Z_TYPE_P(zvalue) == IS_CONSTANT)) {
  7. CHECK_ZVAL_STRING_REL(Z_STR_P(zvalue));
  8. Z_STR_P(zvalue) = zend_string_dup(Z_STR_P(zvalue), 0);
  9. } else if (EXPECTED(Z_TYPE_P(zvalue) == IS_CONSTANT_AST)) {
  10. zend_ast *copy = zend_ast_copy(Z_ASTVAL_P(zvalue));
  11. ZVAL_NEW_AST(zvalue, copy);
  12. }
  13. }

变量的分离

PHP7 中 提供 SEPARATE_STRINGSEPARATE_ARRAY`SEPARATE_ZVALSEPARATE_ZVAL_IF_NOT_REF`等宏定义来实现变量分离。都会预先判断是否需要引用计数(IS_TYPE_REFCOUNTED)的类型,如果需要才会进行分离。

SEPARATE_STRING - 如果类型是 ISTYPE_REFCOUNTED 并且引用计数大于 1,将执行 _zval_copy_ctor_func,并减少自身的引用计数。

SEPARATE_ARRAY - 如果引用计数大于 1,将执行 zval_copy_ctor_func,如果类型不是不可变的(IS_TYPE_IMMUTABLE)将减少原有值的引用计数。

SEPARATE_ZVAL - 如果引用计数大于 1,是可被复制的(ISTYPE_COPYABLE)或是不可变的(IS_TYPE_IMMUTABLE)类型,将执行 _zval_copy_ctor_func,如果是引用类型(ISREFERENCE)的值将先减少自身的引用计数,然后使用 _ZVAL_DUP 复制。

SEPARATE_ZVAL_IF_NOT_REF - 如果类型是可被复制的(ISTYPE_COPYABLE)或是不可变的(IS_TYPE_IMMUTABLE)类型,并且引用计数大于 1 将执行 _zval_copy_ctor_func,如果是引用类型(IS_REFERENCE)的值将使用 `Z_DELREF_P` 先减少自身的引用计数