字串處理是我們常用的操作,而 zend 封裝了很多關於字串操作相關的宏,先看下 ZVAL_STRING 和 ZVAL_STRINGL
#define ZVAL_STRING(z, s, duplicate) do { \constchar *__s=(s); \ zval *__z = (z); \ Z_STRLEN_P(__z) = strlen(__s); \ Z_STRVAL_P(__z) = (duplicate?estrndup(__s, Z_STRLEN_P(__z)):(char*)__s);\ Z_TYPE_P(__z) = IS_STRING; \ } while (0) #define ZVAL_STRINGL(z, s, l, duplicate) do { \constchar *__s=(s); int __l=l; \ zval *__z = (z); \ Z_STRLEN_P(__z) = __l; \ Z_STRVAL_P(__z) = (duplicate?estrndup(__s, __l):(char*)__s);\ Z_TYPE_P(__z) = IS_STRING; \ } while (0)
因為 php 內部很多字串操作(例如 substr)最後都是給予這樣的宏來操作的,所以在這裡瞭解這兩個宏非常重要。
ZVAL_STRINGL 在處理的時候,因為給了 length 參數,所以不需要在使用 strlen 來求字串的長度了, 效能上有所提升。
前面在常用的 zend api 裡面應該說過了,關於 estrndup 也都是封裝了一層的,在 php 擴充開發的時候,盡量使用系統封裝的函數,這樣可以最佳化記憶體,降低記憶體流失等風險,有幾個 e* 開發的函數,可以看之前的相關文章。
estrndup 定義
#define estrndup(s, length) _estrndup((s), (length) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
_estrndup 定義
ZEND_API char *_estrndup(constchar *s, uint length ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) { char *p; #ifdef ZEND_SIGNALS TSRMLS_FETCH(); #endif HANDLE_BLOCK_INTERRUPTIONS(); p = (char *) _emalloc(length+1 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); if (UNEXPECTED(p == NULL)) { HANDLE_UNBLOCK_INTERRUPTIONS(); return p; } memcpy(p, s, length); p[length] = 0; HANDLE_UNBLOCK_INTERRUPTIONS(); return p; }
可以自行搜尋關於 _emalloc 等相關函數定義。
以上就介紹了php擴充開發筆記(6)ZVAL_STRING 和 ZVAL_STRINGL,包括了方面的內容,希望對PHP教程有興趣的朋友有所協助。