PHP の変数名 → zval、変数値 → zend_value。その変数メモリは参照カウントによって管理されます。PHP7 では、参照カウントは値構造内にあります。
ヘッダー ファイルは PHP ソース コード/zend/zend_types.h
## zend_value は共用体であり、そのコードは次のとおりです:
ast 、ptr、zv などの型は、カーネル自体によってのみ使用されます。
文字列:
文字列の内容を格納する val は特殊です。
val は char* 型を使用しません。文字列を割り当てるときは、malloc(sizeof(zend_sting) string length) のように操作されます。これは、文字列の内容を保存するためにより多くのメモリが割り当てられることを意味します。このブロックの追加メモリの開始位置は val です。
val の追加バイト (構造内の val[0] ではなく val[1]) は、保存された文字列の最後の文字 "\0" を保存するために使用されます。
たとえば $a="abc" の場合、対応する zend_string メモリ構造は左のとおりです。
この値は、ハッシュ関数がキーのハッシュ コード要素に基づいて場所を保存するときに使用されます。 nTableMask = -nTableSize または nTableMask = ~nTableSize 1.
nNumused, nNumOfElements:配列要素を削除する場合、要素はすぐには配列から削除されません。代わりに、要素の型は IS_UNDEF としてマークされます。これは使用されるだけです。アレイの容量が制限を超えて拡張する必要がある場合にのみ削除されます。
展開がない場合、nNum Used は常に増加するため、その値は有効な要素数ではありません。 nNumOfElements は配列内の有効な要素の数であるため、nNumOfElements ≤ nNum Used になります。
バケット配列の実装:
ハッシュ テーブルの順序性を実現するために、PHP のハッシュ テーブルはハッシュ関数と要素の間に要素を追加します。配列. レイヤーマッピングテーブル、このマッピングテーブルも配列であり、サイズは要素を格納する配列と同じです。中間マッピング テーブルは、実際に格納された順序付けされた配列内の要素の添字を格納します。要素は実際の格納配列に順番に挿入され、その配列の添字はハッシュ関数によってハッシュされた位置に格納されます。新しく追加されたマッピングテーブル。
ハッシュ関数:
要素の保存場所はキーに従ってマッピングされます。通常、モジュロがハッシュ関数として使用されます: key-> ;h %nテーブルサイズ。しかし、PHP は別のアプローチ (nIndex = key->h | nTableMask) を採用しています。
この中間マッピング テーブルは PHP 配列の構造には存在せず、実際には arData と一緒に配置されます。配列が初期化されると、バケットを格納するために使用されるメモリが割り当てられ、同時に uint32_t サイズの同量のスペースが割り当てられます。次に、要素の配列が格納されている場所に arData をオフセットします。 中間マッピング テーブルには、arData を介して前方にアクセスできます。
ハッシュの競合:
異なるキー値が同じハッシュ値を計算する可能性があり、ハッシュ テーブルに挿入するときに競合が発生します。 table 要素は 1 つだけ格納できます。
解決策: 競合するバケットをリンク リストに文字列化します。つまり、中間マッピング テーブルは、バケットではなくバケットのリンク リストをマップします。検索するときは、このリンク リストを横断し、キーを 1 つずつ比較して検索する必要があります。ターゲット要素。
HashTable は、arData 配列内で競合する要素の保存場所を記録します。
マッピング値を設定するときに、中間マッピング テーブルに設定する位置が、以前に挿入された要素によって占有されていることがわかりました (値が等しくない)初期化された -1)、既存の値を新しく挿入されたバケット (つまり、c が挿入された後の u2.next=0) に保存し、マッピング テーブル内の値を新しいバケットの保存場所に更新します。 (つまり、マッピング テーブルの値: 2)。
リファレンスは、C 言語のポインターの概念に似た、他の型を指す構造体です。参照型変数を変更すると、その変更は実際に参照される変数に反映されます。
PHP では、$b = &$a などの & 演算子を通じて参照変数が生成されます。実行中、最初に zend_reference 構造体が & 演算の変数に割り当てられます。この構造体は参照です。 type 構造体。zval が埋め込まれており、この zval の値は元の zval の値を指します。その後、元の zval の型は IS_REFERENCE に変更され、元の zval の値は新しく作成された zend_reference 構造体を指します。
#例:$a = date("Y-m");$b = &$a;$a は文字列です&$a を介して参照型に変換し、$b に割り当てます。変換後、$a の型は IS_STRING から IS_REFERENCE に変更され、$a の値も zend_reference 構造体に変換されます。オリジナルの文字列。 $a と $b は、実際の値を間接的に指します。 参照を使用する場合は注意が必要です。参照は & を通じてのみ生成でき、代入を通じて渡すことはできません。 上記の例のように、$b が他の変数に割り当てられている場合、新しい変数に渡される値は、参照自体ではなく、実際の参照の値になります。
$a = date("Y-m");$b = &$a;$c = $b; //如果想让$c也引用指向$a/$b引用的值,则:$c = &$b
以上がPHP7のデータ型の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。