PHP 拡張機能の開発 - 配列の使用と HashTable_PHP チュートリアルの概要
hashtable
php
一度
使用
存在する
開発する
私たち
拡大する
配列
の
導入
1 アレイ
このセクションでは、PHP 配列について説明します。PHP では、配列は HashTable を使用して実装されます。このセクションでは、まず HashTable について詳しく紹介し、その後、HashTable の使用方法について説明します
1.1 可変長構造
いわゆる可変長構造は、実際には C 言語構造の特別な使用法であり、それについては何も目新しいものではありません。まずは可変長構造体の一般的な定義方法を見てみましょう。
typedef 構造体バケット {
int;
文字キー[30];
文字値[1];
}バケツ;
バケット構造を定義しました。この構造を使用して生徒の個人プロファイルを保存したいと考えています。キーは学生の名前を保存するために使用され、値は学生のプロファイルを保存するために使用されます。興味があるかもしれませんが、この値は長さ 1 を宣言しています。1 文字にどれだけの情報を格納できるでしょうか?
実際、長い構造の場合、次のような変数を直接定義することはできません。 このように使用すると、Value には多くの情報が格納されなくなります。可変長構造体の場合、使用するときにまず可変長構造体へのポインタを宣言し、次に malloc 関数を通じて関数空間を割り当てる必要があります。使用する必要がある空間の長さに応じて malloc することができます。一般的な使用方法は次のとおりです。 void *pDataPtr;
structbucket *pListNext; //前の要素
;
struct Bucket *pListLast; //次の要素
structbucket *pNext; //次のバケットへのポインタ
structbucket *pLast //前のバケットへのポインタ
char arKey[1] //主に可変長構造を実現するために最後に配置する必要があります
}バケツ;
typedef struct _hashtable {
uint nTableSize //ハッシュテーブルのサイズ
uint nTableMask; //数値的には nTableSize- 1 に等しい
uint nNumOfElements; // 現在の HashTable に保存されているレコードの数を記録します
ulong nNextFreeElement //次の空きバケットを指します
Bucket *pInternalPointer; //この変数は配列の反転に使用されます
Bucket *pListHead //バケットの先頭を指します
Bucket *pListTail // Bucket の末尾を指します
バケット **arBuckets;
dtor_func_t pDestructor; // 配列の追加、削除、変更、チェック時に自動的に呼び出され、特定のクリーニング操作に使用される関数ポインター
zend_bool // 永続的ですか?
unsigned char nApplyCount;if((ht) - > bapplyprotection){
zend_error(E_ERROR, "ネストレベルが深すぎます - 再帰的な依存関係?");
}
このマクロは主に循環参照を防ぐために使用されます。
1.3.2 マクロ ZEND_HASH_IF_FULL_DO_RESIZE
#defineZEND_HASH_IF_FULL_DO_RESIZE(ht)
if ((ht)->nNumOfElements >(ht)->nTableSize) {
zend_hash_do_resize(ht);
}
ht->nTableSize = 1 <
} }
このマクロの機能は、現在の HashTable 内の要素の数が HashTable の合計サイズより大きいかどうかを確認することです。その数が HashTable のサイズより大きい場合、スペースを再割り当てします。 zend_hash_do_resize を見てみましょう
static int zend_hash_do_resize(HashTable *ht)
{
バケツ **t;
IS_CONSISTENT(ht);
if ((ht->nTableSize << 1) > 0) { /* テーブルサイズを 2 倍にしましょう */
t = (バケット**) perrealloc_recoverable(ht->arBuckets,
)
(ht->nTableSize persistent);
if (t) {
HANDLE_BLOCK_INTERRUPTIONS();
ht->arBuckets = t;
ht->nTableSize = (ht->nTableSize
{
uint i = 3; //デフォルトでは HashTable のサイズは 2 の 3 乗ではありません
バケツ**tmp;
SET_INCONSISTENT(HT_OK);
if (nSize >= 0x80000000) {
ht->nTableSize = 0x80000000;
} 他 {
while ((1U
i++; ht->nTableMask = ht->nTableSize - 1;
zend_hash_rehash(ht);
HANDLE_UNBLOCK_INTERRUPTIONS();
成功を返す;
}
返品失敗;
}
成功を返します;
}
上記のコードから、HashTable がスペースを割り当てるとき、新しく割り当てられたスペースは元のスペースの 2 倍に等しいことがわかります。
1.3.3 関数_zend_hash_init
この関数は HashTable を初期化するために使用されます。まずコードを見てみましょう。
ZEND_API int _zend_hash_init(HashTable *ht, uint nSize, hash_func_t pHashFunction, dtor_func_t pDestructor, zend_bool 永続的 ZEND_FILE_LINE_DC) }
ht->arBuckets = tmp;
} 他 {
tmp = (バケット **) ecalloc_rel(ht->nTableSize, sizeof(Bucket*));
if (tmp) {
ht->arBuckets = tmp;
}
}
成功を返します;
}
HashTable のサイズが 2 の n 乗に初期化されていることがわかります。さらに、2 つのメモリ メソッドがあることがわかります。1 つは calloc で、もう 1 つは ecalloc_rel です。これら 2 つのメモリ割り当てメソッドについて詳しく説明しました。興味があれば、自分で調べてみてください。
1.3.4 Function_zend_hash_add_or_update
この関数はHashTableに要素情報を追加または変更します
ZEND_API int _zend_hash_add_or_update(HashTable *ht, const char *arKey, uint nKeyLength, void *pData, uint nDataSize, void **pDest, int flag ZEND_FILE_LINE_DC)
{
うろんh;
uint nIndex;
バケツ *p;
IS_CONSISTENT(ht);
if (nKeyLength <= 0) {
#if ZEND_DEBUG
ZEND_PUTS("zend_hash_update: 空のキーンを置くことはできません");
#endif
返品失敗;
}
h = zend_inline_hash_func(arKey, nKeyLength);
nIndex = h & ht->nTableMask;
p = ht->arBuckets[nIndex];
while (p != NULL) {
if ((p->h == h) && (p->nKeyLength == nKeyLength)) {
if (!memcmp(p->arKey, arKey, nKeyLength)) {
if (フラグ & HASH_ADD) {
失敗を返す;
}
HANDLE_BLOCK_INTERRUPTIONS();
#if ZEND_DEBUG
if (p->pData == pData) {
ZEND_PUTS("zend_hash_update:p->pData == pDatan");
HANDLE_UNBLOCK_INTERRUPTIONS();
失敗を返す;
}
#endif
if (ht->pDestructor) {
ht->pDestructor(p->pData);
}
UPDATE_DATA(ht, p, pData, nDataSize);
if (pDest) {
*pDest = p->pData;
}
HANDLE_UNBLOCK_INTERRUPTIONS();
成功を返す;
}
}
p = p->pNext;
}
p = (バケット *) pemalloc(sizeof(バケット) - 1 + nKeyLength, ht->persistent);
if (!p) {
返品失敗;
}
memcpy(p->arKey, arKey, nKeyLength);
p->nKeyLength = nKeyLength;
INIT_DATA(ht, p, pData, nDataSize);
p->h = h;
CONNECT_TO_BUCKET_DLLIST(p, ht->arBuckets[nIndex]);
if (pDest) {
*pDest = p->pData;
}
ハンドル_ブロック_中断();
CONNECT_TO_GLOBAL_DLLIST(p, ht);
ht->arBuckets[nIndex] = p;
HANDLE_UNBLOCK_INTERRUPTIONS();
ht->nNumOfElements++;
ZEND_HASH_IF_FULL_DO_RESIZE(ht); /* ハッシュ テーブルがいっぱいの場合は、サイズを変更します */
成功を返します;
}
1.3.5 マクロ CONNECT_TO_BUCKET_DLLIST
#define CONNECT_TO_BUCKET_DLLIST(要素, list_head)
(要素)->pNext= (list_head);
(要素)->pLast= NULL;
if((要素)->pNext) {
(要素)->pNext->pLast =(要素);
}
このマクロはバケットをバケットリストに追加するものです
1.3.6 その他の関数またはマクロ定義
HashTable について簡単に紹介します。HashTable を詳しく理解したい場合は、HashTable のコードは Zend/zend_hash.h と Zend/zend_hash.c にあります。
zend_hash_add_empty_element は関数に空の要素を追加します
zend_hash_del_key_or_index はインデックスに基づいて要素を削除します
zend_hash_reverse_apply 逆走査ハッシュテーブル
zend_hash_copy コピー
_zend_hash_merge マージ
zend_hash_find 文字列インデックス検索
zend_hash_index_find 数値インデックス方式検索
zend_hash_quick_find 上記 2 つの関数のカプセル化
zend_hash_exists インデックスが存在するかどうか
zend_hash_index_exists インデックスが存在するかどうか
zend_hash_quick_exists は上記の 2 つのメソッドをカプセル化します
1.4 C拡張でよく使われるHashTable関数
HashTable は少し複雑に見えますが、次の関数を使用して HashTable に値を初期化して割り当てることができます。
2005年の地元の大学の入学者数
PHP 構文
C 構文
意味
$arr = array()
array_init(arr);
配列を初期化する
$arr[] = NULL;
add_next_index_null(arr);
$arr[] = 42;
add_next_index_long(arr, 42);
$arr[] = true;
add_next_index_bool(arr, 1);
$arr[] = 3.14;
add_next_index_double(3.14);
$arr[] = 'foo';
add_next_index_string(arr, “foo”, 1);
1 は文字列のコピーを意味します
$arr[] = $myvar;
add_next_index_zval(arr, myvar);
$arr[0] = NULL;
add_index_null(arr, 0);
$arr[1] = 42;
add_index_long(arr, 1, 42);
$arr[2] = true;
add_index_bool(arr, 2, 1);
$arr[3] = 3.14;
add_index_double(arr, 3, 3,14);
$arr[4] = 'foo';
add_index_string(arr, 4, “foo”, 1);
$arr[5] = $myvar;
add_index_zval(arr, 5, myvar);
$arr["abc"] = NULL;
add_assoc_null(arr, “abc”);
$arr["def"] = 711;
add_assoc_long(arr, “def”, 711);
$arr["ghi"] = true;
add_assoc_bool(arr, ghi”, 1);
$arr["jkl"] = 1.44;
add_assoc_double(arr, “jkl”, 1.44);
$arr[“mno”] = 'バズ';
add_assoc_string(arr, “mno”, “baz”, 1);
$arr[‘pqr’] = $myvar;
add_assoc_zval(arr, “pqr”, myvar);
1.5 タスクと実験
ここまで述べたので、実験してみましょう。
タスク: 配列を返します。配列内のデータは次のとおりです。
配列
& [0] = & gt;
) add_next_index_string(return_value, "テスト用", 1);
add_index_long(return_value, 42, 123);
add_assoc_double(return_value, "テスト用。テスト用。", 1.0);
ALLOC_INIT_ZVAL(t);
array_init(t);
add_next_index_double(t, 3.34);
add_assoc_zval(return_value, "array", t);
}
とても簡単です。return_value を覚えていますか?
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事
R.E.P.O.説明されたエネルギー結晶と彼らが何をするか(黄色のクリスタル)
3週間前
By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最高のグラフィック設定
3週間前
By 尊渡假赌尊渡假赌尊渡假赌
アサシンのクリードシャドウズ:シーシェルリドルソリューション
1週間前
By DDD
R.E.P.O.誰も聞こえない場合はオーディオを修正する方法
3週間前
By 尊渡假赌尊渡假赌尊渡假赌
Atomfallのクレーンコントロールキーカードを見つける場所
1週間前
By DDD

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック

PHP 8.4 では、いくつかの新機能、セキュリティの改善、パフォーマンスの改善が行われ、かなりの量の機能の非推奨と削除が行われています。 このガイドでは、Ubuntu、Debian、またはその派生版に PHP 8.4 をインストールする方法、または PHP 8.4 にアップグレードする方法について説明します。

CakePHP でデータベースを操作するのは非常に簡単です。この章では、CRUD (作成、読み取り、更新、削除) 操作について理解します。

ファイルのアップロードを行うには、フォーム ヘルパーを使用します。ここではファイルアップロードの例を示します。

CakePHP は、PHP 用のオープンソース フレームワークです。これは、アプリケーションの開発、展開、保守をより簡単にすることを目的としています。 CakePHP は、強力かつ理解しやすい MVC のようなアーキテクチャに基づいています。モデル、ビュー、コントローラー
