Анатомия zval: Основные компоненты (PHP 7+)

В этой статье мы детально разберём структуру zval в современных версиях PHP, начиная с революционного PHP 7. Вы узнаете, как организовано хранение переменных на низком уровне и какие оптимизации были внедрены.

2.1. Основные компоненты zval

Структура _zval_struct

struct _zval_struct {
    zend_value value;    // Основное значение (64 бита)
    union {
        struct {
            zend_uchar type;         // Тип данных (IS_LONG, IS_STRING и др.)
            zend_uchar type_flags;    // Флаги поведения типа
            zend_uchar const_flags;   // Флаги константности
            zend_uchar reserved;      // Зарезервировано
        } v;
        uint32_t type_info;           // Альтернативное представление
    } u1;                            // 32 бита
    union u2 {                       // 32 бита (служебные данные)
        uint32_t next;               // Для управления хеш-таблицами
        uint32_t cache_slot;         // Кеширование
        uint32_t lineno;             // Номер строки (для ошибок)
        uint32_t num_args;           // Количество аргументов
        uint32_t fe_pos;             // Позиция в foreach
        // ... другие служебные поля
    };
}; // Всего 16 байт

1. Компонент value (zend_value)

ТипПолеРазмерОписание
Целоеlval64 битаДля типов IS_LONG, IS_BOOL
Дробноеdval64 битаДля IS_DOUBLE
Указательstr64 битаДля строк (IS_STRING)
Указательarr64 битаДля массивов (IS_ARRAY)

2. Компонент u1 (метаданные типа)

  • type — определяет базовый тип данных (IS_LONG, IS_STRING и др.)
  • type_flags — дополнительные флаги поведения:
    • IS_TYPE_REFCOUNTED (требует подсчета ссылок)
    • IS_TYPE_COPYABLE (поддерживает Copy-On-Write)
    • IS_TYPE_IMMUTABLE (неизменяемый тип)
  • const_flags — флаги константности

3. Компонент u2 (служебные данные)

Этот компонент используется для различных оптимизаций:

  • next — связь элементов в хеш-таблицах
  • cache_slot — кеширование для быстрого доступа
  • lineno — отладка (номер строки в исходном коде)
  • num_args — информация о вызовах функций

Практический пример

// Создание zval с целым числом
zval my_zval;
ZVAL_LONG(&my_zval, 42);

// Доступ к данным
if (Z_TYPE(my_zval) == IS_LONG) {
    zend_long value = Z_LVAL(my_zval); // 42
    php_printf("Значение: %ld\n", value);
}

Продолжение следует в следующей статье цикла…

Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *