動的な配列サイズの増やし方 - PHPの場合
もう誰か触れてそうなもんだけど。
PHP : 2 倍?(これは PHP から使う配列の実装とは別物かな…?)
// Zend/zend_dynamic_array.c : 43行目〜 if (da->current == da->allocated) { da->allocated *= 2;http://www.kmonos.net/wlog/111.html?_2334100705
PHP の場合、動的に配列サイズが変更される箇所は、
- 文字列連結
- 連想配列
の2つだけど *1、後者はハッシュテーブルなので、例の議論は当てはまらない。なので前者だけを見る。
上の zend_dynamic_array.c は関係ありません><
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); } if (use_copy1) { /* We have created a converted copy of op1. Therefore, op1 won't become the result so * we have to free it. */ if (result == op1) { zval_dtor(op1); } op1 = &op1_copy; } if (use_copy2) { op2 = &op2_copy; } if (result==op1) { /* special case, perform operations on result */ uint res_len = Z_STRLEN_P(op1) + Z_STRLEN_P(op2); if (Z_STRLEN_P(result) < 0 || (int) (Z_STRLEN_P(op1) + Z_STRLEN_P(op2)) < 0) { efree(Z_STRVAL_P(result)); ZVAL_EMPTY_STRING(result); zend_error(E_ERROR, "String size overflow"); } Z_STRVAL_P(result) = erealloc(Z_STRVAL_P(result), res_len+1); memcpy(Z_STRVAL_P(result)+Z_STRLEN_P(result), Z_STRVAL_P(op2), Z_STRLEN_P(op2)); Z_STRVAL_P(result)[res_len]=0; Z_STRLEN_P(result) = res_len; } else { Z_STRLEN_P(result) = Z_STRLEN_P(op1) + Z_STRLEN_P(op2); Z_STRVAL_P(result) = (char *) emalloc(Z_STRLEN_P(result) + 1); memcpy(Z_STRVAL_P(result), Z_STRVAL_P(op1), Z_STRLEN_P(op1)); memcpy(Z_STRVAL_P(result)+Z_STRLEN_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op2)); Z_STRVAL_P(result)[Z_STRLEN_P(result)] = 0; Z_TYPE_P(result) = IS_STRING; } if (use_copy1) { zval_dtor(op1); } if (use_copy2) { zval_dtor(op2); } return SUCCESS; } /* }}} */
PHP で文字列を格納する構造体には、容量という概念がない。なので、文字列を同じ変数に対して連結していくときも、(連結元のサイズ) + (連結対象のサイズ) で realloc してるだけでした。
*1:拡張モジュールなどで独自に実装している場合はあるけど、ここではユーザが直に触れられるものだけを扱う