ホームページ >バックエンド開発 >PHPチュートリアル >PHPカスタム関数のパラメータ受け渡しについての深い理解

PHPカスタム関数のパラメータ受け渡しについての深い理解

伊谢尔伦
伊谢尔伦オリジナル
2017-06-26 13:29:151548ブラウズ

関数のパラメータ

関数の定義は、関数リストに関数名を登録するだけの処理です。

1. ユーザー定義関数のパラメーター

この関数のパラメーターのチェックは zend_do_receive_arg 関数を通じて実装されていることがわかります:

CG(active_op_array)->arg_info = erealloc(CG(active_op_array)->arg_info,
        sizeof(zend_arg_info)*(CG(active_op_array)->num_args));
cur_arg_info = &CG(active_op_array)->arg_info[CG(active_op_array)->num_args-1];
cur_arg_info->name = estrndup(varname->u.constant.value.str.val,
        varname->u.constant.value.str.len);
cur_arg_info->name_len = varname->u.constant.value.str.len;
cur_arg_info->array_type_hint = 0;
cur_arg_info->allow_null = 1;
cur_arg_info->pass_by_reference = pass_by_reference;
cur_arg_info->class_name = NULL;
cur_arg_info->class_name_len = 0;

パラメーター全体が渡されます。 to 中間コードの arg_info フィールドへの代入操作が完了しました。重要な点は arg_info フィールドにあり、arg_info フィールドの構造は次のとおりです。

typedef struct _zend_arg_info {
    const char *name;   /*参数的名称*/
    zend_uint name_len;     /*参数名称的长度*/
    const char *class_name; /* 类名*/
     zend_uint class_name_len;   /*类名长度*/
    zend_bool array_type_hint;  /*数组类型提示*/
    zend_bool allow_null;   /*是否允许为NULLͺ*/
    zend_bool pass_by_reference;    /*是否引用传递*/
    zend_bool return_reference; 
    int required_num_args;  
} zend_arg_info;

パラメーター値の受け渡しとパラメーターの受け渡しの違いは、中間コードの生成時に pass_by_reference パラメーターによって実現されます。

パラメータの数については、**zend_do_receive_argxx が実行されるたびに、中間コードに含まれる arg_nums フィールドが 1 ずつ増加します:

CG(active_op_array)->num_args++;

そして、現在のパラメータのインデックスは CG(active_op_array)-> です。 ;num_args-1 .次のコード:

cur_arg_info = &CG(active_op_array)->arg_info[CG(active_op_array)->num_args-1];

上記の解析は関数定義時のパラメータ設定に基づいており、これらのパラメータは固定されています。実際にプログラムを書く際には

変数パラメータを使用することがあります。このとき、関数 func_num_args と func_get_args を使用します。これらは 内部関数 として存在します。したがって、Zendzend_builtin_functions.c ファイルでこれら 2 つの関数の実装を見つけてください。まず func_num_args 関数の実装を見てみましょう。 コードは次のとおりです。

/* {{{ proto int func_num_args(void)
   Get the number of arguments that were passed to the function */
ZEND_FUNCTION(func_num_args)
{
    zend_execute_data *ex = EG(current_execute_data)->prev_execute_data;
 
    if (ex && ex->function_state.arguments) {
        RETURN_LONG((long)(zend_uintptr_t)*(ex->function_state.arguments));
    } else {
        zend_error(E_WARNING,
"func_num_args():  Called from the global scope - no function context");
        RETURN_LONG(-1);
    }
}
/* }}} */

ex->function_state.arguments が存在し、関数が呼び出された場合、ex->function_state.arguments の変換された値が返されます。それ以外の場合はエラーが表示され、-1 が返されます。ここで最も重要なポイントは EG (current_execute_data) です。この変数には、現在実行中のプログラムまたは関数のデータが格納されています。なぜなら、この関数の呼び出しは関数に入った後に実行されるからです。関数の関連データはすべて前の実行プロセスにあるため、呼び出されるのは次のとおりです:

zend_execute_data *ex = EG(current_execute_data)->prev_execute_data;

2. 内部関数のパラメータ

共通の count 関数を例にとると、パラメータ処理部分のコードは次のようになります。

/* {{{ proto int count(mixed var [, int mode])
   Count the number of elements in a variable (usually an array) */
PHP_FUNCTION(count)
{
    zval *array;
    long mode = COUNT_NORMAL;
 
    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|l",
         &array, &mode) == FAILURE) {
        return;
    }
    ... //省略
}

これには 2 つの操作が含まれています。1 つはパラメーターの数を取得することで、もう 1 つはパラメーター リストを解析することです。

(1) パラメータの数を取得します

パラメータの数の取得は、次のように定義されている ZEND_NUM_ARGS() マクロによって実現されます:

#define ZEND_NUM_ARGS()     (ht)

ht は、Zend/zend.h ファイルで定義されたマクロ INTERNAL_FUNCTION_PARAMETERS にあります。 ht、以下の通り

#define INTERNAL_FUNCTION_PARAMETERS int ht, zval *return_value,
zval **return_value_ptr, zval *this_ptr, int return_value_used TSRMLS_DC

(2) パラメータの解析リスト

PHPの内部関数はパラメータを解析する際にzend_parse_parametersを使用します。パラメーターの受信と処理の作業を大幅に簡素化できますが、可変パラメーターを扱う場合にはまだ少し弱いです。

次のように宣言されます:

ZEND_API int zend_parse_parameters(int num_args TSRMLS_DC, char *type_spec, 
...)

最初のパラメータ num_args は、受信パラメータを「必要なだけ」表現するために ZEND_NUM_ARGS() をよく使用します

2 番目のパラメータは次のようになります。マクロ TSRMLS_CC です。

3 番目のパラメーター type_spec は、受け取ることが期待される各パラメーターの型を指定するために使用される文字列で、printf で出力形式を指定する

フォーマットされた文字列 に似ています。

残りのパラメーターは、PHP パラメーター値を受け取るために使用する変数へのポインターです。

zend_parse_parameters() は、パラメーターの解析中に可能な限りパラメーターの型を変換し、常に期待される型の変数を取得できるようにします

以上がPHPカスタム関数のパラメータ受け渡しについての深い理解の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。