<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                PHP是弱類型的動態語言,在前面的章節中我們已經介紹了PHP的變量都存放在一個名為ZVAL的容器中,ZVAL包含了變量的類型和各種類型變量的值。PHP中的變量不需要顯式的數據類型定義,可以給變量賦值任意類型的數據,PHP變量之間的數據類型轉換有兩種: 隱式和顯式轉換。 ## 隱式類型轉換[]() 隱式類型轉換也被稱為自動類型轉換,是指不需要程序員書寫代碼,由編程語言自動完成的類型轉換。在PHP中,我們經常遇到的隱式轉換有: 1.**直接的變量賦值操作** 在PHP中,直接對變量的賦值操作是隱式類型轉換最簡單的方式,也是我們最常見的一種方式,或許我們已經習以為常,從而沒有感覺到變量的變化。在直接賦值的操作中,變量的數據類型由賦予的值決定,即左值的數據類型由右值的數據類型決定。比如,當把一個字符串類型的數據賦值給變量時,不管該變量以前是什么類型的變量,此時該變量就是一個字符串類型的變量。看一段代碼: $string = "To love someone sincerely means to love all the people, to love the world and life, too."; $integer = 10; $string = $integer; 上面的代碼,當執行完第三行代碼,$string變量的類型就是一個整形了。通過VLD擴展可以查到第三次賦值操作的中間代碼及操作數的類型,再找到賦值的最后實現為**zend_assign_to_variable**函數。這在前面的小節中已經詳細介紹過了。我們這個例子是很簡單的一種賦值,在源碼中是直接將$string的ZVAL容器的指針指向$integer變量指向的指針,并將$integer的引用計數加1。這個操作在本質上改變了$string變量的內容,而原有的變量內容則被垃圾收集機制回收。關于賦值的具體細節,請返回[上一節(變量的賦值和銷毀)](#)查看。 2.**運算式結果對變量的賦值操作**我們常說的隱式類型轉換是將一個表達式的結果賦值給一個變量,在運算的過程中發生了隱式的類型轉換。這種類型轉換不僅僅在PHP語言,在其它眾多的語言中也有見到,這是我們常規意義上的隱式類型轉換。這種類型轉換又分為兩種情況: - 表達式的操作數為同一數據類型 這種情況的作用以上面的直接變量的類型轉換是同一種情況,只是此時右值變成了表達式的運算結果。 - 表達式的操作數不為同的數據類型 這種情況的類型轉換發生在表達式的運算符的計算過程中,在源碼中也就是發生在運行符的實現過程中。 看一個字符串和整數的隱式數據類型轉換: <?php $a = 10; $b = 'a string '; ? [echo](http://www.php.net/echo) $a . $b; 上面例子中字符串連接操作就存在自動數據類型轉化,$a變量是數值類型,$b變量是字符串類型,這里$a變量就是隱式(自動)的轉換為字符串類型了。通常自動數據類型轉換發生在特定的操作上下文中,類似的還有求和操作"+"。具體的自動類型轉換方式和特定的操作有關。下面就以字符串連接操作為例說明隱式轉換的實現: 腳本執行的時候字符串的連接操作是通過Zend/zend_operators.c文件中的如下函數進行: ZEND_API int concat_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */ { zval op1_copy, op2_copy; int use_copy1 = 0, use_copy2 = 0; ? if (Z_TYPE_P(op1) != IS_STRING) { zend_make_printable_zval(op1, &op1_copy, &use_copy1); } if (Z_TYPE_P(op2) != IS_STRING) { zend_make_printable_zval(op2, &op2_copy, &use_copy2); } // 省略 } 可用看出如果字符串鏈接的兩個操作數如果不是字符串的話,則調用zend_make_printable_zval函數將操作數轉換為"printable_zval"也就是字符串。 ZEND_API void zend_make_printable_zval(zval *expr, zval *expr_copy, int *use_copy) { if (Z_TYPE_P(expr)==IS_STRING) { *use_copy = 0; return; } switch (Z_TYPE_P(expr)) { case IS_NULL: Z_STRLEN_P(expr_copy) = 0; Z_STRVAL_P(expr_copy) = STR_EMPTY_ALLOC(); break; case IS_BOOL: if (Z_LVAL_P(expr)) { Z_STRLEN_P(expr_copy) = 1; Z_STRVAL_P(expr_copy) = estrndup("1", 1); } else { Z_STRLEN_P(expr_copy) = 0; Z_STRVAL_P(expr_copy) = STR_EMPTY_ALLOC(); } break; case IS_RESOURCE: // ...省略 case IS_ARRAY: Z_STRLEN_P(expr_copy) = sizeof("Array") - 1; Z_STRVAL_P(expr_copy) = estrndup("Array", Z_STRLEN_P(expr_copy)); break; case IS_OBJECT: // ... 省略 case IS_DOUBLE: *expr_copy = *expr; zval_copy_ctor(expr_copy); zend_locale_sprintf_double(expr_copy ZEND_FILE_LINE_CC); break; default: *expr_copy = *expr; zval_copy_ctor(expr_copy); convert_to_string(expr_copy); break; } Z_TYPE_P(expr_copy) = IS_STRING; *use_copy = 1; } 這個函數根據不同的變量類型來返回不同的字符串類型,例如BOOL類型的數據返回0和1,數組只是簡單的返回Array等等,類似其他類型的數據轉換也是類型,都是根據操作數的不同類型的轉換為相應的目標類型。在表達式計算完成后,表達式最后會有一個結果,這個結果的數據類型就是整個表達式的數據類型。當執行賦值操作時,如果再有數據類型的轉換發生,則是直接變量賦值的數據類型轉換了。 ## 顯式類型轉換(強制類型轉換)[]() 在前面介紹了隱式類型轉換,在我們的日常編碼過程也會小心的使用這種轉換,這種不可見的操作可能與我們想象中的不一樣,如整形和浮點數之間的轉換。當我們是一定需要某個數據類型的變量時,可以使用強制的數據類型轉換,這樣在代碼的可讀性等方面都會好些。在PHP中的強制類型轉換和C中的非常像: <?php $double = 20.10; [echo](http://www.php.net/echo) (int)$double; PHP中允許的強制類型有: - (int), (integer) 轉換為整型 - (bool), (boolean) 轉換為布爾類型 - (float), (double) 轉換為浮點類型 - (string) 轉換為字符串 - (array) 轉換為數組 - (object) 轉換為對象 - (unset) 轉換為NULL 在Zend/zend_operators.c中實現了轉換為這些目標類型的實現函數convert_to_*系列函數,讀者自行查看這些函數即可,這些數據類型轉換類型中有一個我們比較少見的unset類型轉換: ZEND_API void convert_to_null(zval *op) /* {{{ */ { if (Z_TYPE_P(op) == IS_OBJECT) { if (Z_OBJ_HT_P(op)->cast_object) { zval *org; TSRMLS_FETCH(); ? ALLOC_ZVAL(org); *org = *op; if (Z_OBJ_HT_P(op)->cast_object(org, op, IS_NULL TSRMLS_CC) == SUCCESS) { zval_dtor(org); return; } *op = *org; FREE_ZVAL(org); } } ? zval_dtor(op); Z_TYPE_P(op) = IS_NULL; } 轉換為NULL非常簡單,對變量進行析構操作,然后將數據類型設為IS_NULL即可。可能讀者會好奇(unset)$a和unset($a)這兩者有沒有關系,其實并沒有關系,前者是將變量$a的類型變為NULL,這只是一個類型的變化,而后者是將這個變量釋放,釋放后當前作用域內該變量就不存在了。 除了上面提到的與C語言很像,在其它語言中也經常見到的強制數據轉換,PHP中有一個極具PHP特色的強制類型轉換。PHP的標準擴展中提供了兩個有用的方法settype()以及gettype()方法,前者可以動態的改變變量的數據類型,gettype()方法則是返回變量的數據類型。在ext/standard/type.c文件中找到settype的實現源碼: PHP_FUNCTION(settype) { zval **var; char *type; int type_len = 0; ? if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Zs", &var, &type, &type_len) == FAILURE) { return; } ? if (!strcasecmp(type, "integer")) { convert_to_long(*var); } else if (!strcasecmp(type, "int")) { convert_to_long(*var); } else if (!strcasecmp(type, "float")) { convert_to_double(*var); } else if (!strcasecmp(type, "double")) { /* deprecated */ convert_to_double(*var); } else if (!strcasecmp(type, "string")) { convert_to_string(*var); } else if (!strcasecmp(type, "array")) { convert_to_array(*var); } else if (!strcasecmp(type, "object")) { convert_to_object(*var); } else if (!strcasecmp(type, "bool")) { convert_to_boolean(*var); } else if (!strcasecmp(type, "boolean")) { convert_to_boolean(*var); } else if (!strcasecmp(type, "null")) { convert_to_null(*var); } else if (!strcasecmp(type, "resource")) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot convert to resource type"); RETURN_FALSE; } else { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid type"); RETURN_FALSE; } RETVAL_TRUE; } 這個極具PHP特色的強制類型轉換就是這個函數,而這個函數是作為一個代理方法存在,具體的轉換規則由各個類型的處理函數處理,不管是自動還是強制類型轉換,最終都會調用這些內部轉換方法,這和前面的強制類型轉換在本質上是一樣的。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看