Типы данных: всего четыре числа

Изучаем числовые типы Wasm и понимаем, почему их так мало.

Базовые типы Wasm — это i32, i64, f32, f64: два целых и два с плавающей точкой, по 32 и 64 бита.

Четыре типа — и всё

Если вы привыкли к десяткам типов из C++ или Java, аскетизм Wasm удивит. На уровне ядра у Wasm всего четыре числовых типа:

ТипЧто этоАналог в C
i3232-битное целоеint
i6464-битное целоеlong long
f3232-битное число с плавающей точкойfloat
f6464-битное число с плавающей точкойdouble

А где строки, массивы, булевы?

Их на этом уровне нет — и это сделано намеренно. WebAssembly спроектирован максимально близко к тому, что умеет реальный процессор, а процессор знает только целые и дробные числа разной ширины. Всё остальное — надстройка:

  • Булево — это i32: 0 значит «ложь», любое ненулевое — «истина».
  • Символы и байты — это i32 с маленьким значением (например, код символа).
  • Строки и массивы — это последовательности байт в линейной памяти; через границу передают адрес (i32) и длину (i32).
  • Знаковость не хранится в типе: i32 — просто 32 бита. Знаковое или нет — решает конкретная инструкция (i32.div_s против i32.div_u).

Знаковые и беззнаковые операции

Тип i32 один, а вот операций над ним две версии — со знаком (_s, signed) и без (_u, unsigned). Сравним деление на JS-модели, где это видно явно при работе с большими беззнаковыми значениями.

const bits = 0xFFFFFFFF;        // все 32 бита единицы
console.log("как unsigned:", bits >>> 0);   // 4294967295
console.log("как signed:", bits | 0);       // -1

Вывод:

как unsigned: 4294967295
как signed: -1

Одни и те же 32 бита читаются как 4294967295 или как -1 — всё зависит от того, какой операцией мы их трактуем. Ровно так же устроен i32 в Wasm.

Как работает под капотом

Малое число типов делает Wasm-движок простым и быстрым. Валидатору легко проверить, что в f64.add приходят два f64, а не строки. Компилятору легко отобразить четыре типа Wasm на регистры процессора, которые ровно эти четыре формы и поддерживают. Чем меньше сущностей, тем меньше места для ошибок и тем выше предсказуемость.

Частые ошибки в понимании

  • «В Wasm есть тип string» — нет, строка живёт в памяти как байты, через границу идёт адрес и длина.
  • «i32 — это знаковое число» — i32 это просто 32 бита; знаковость определяет инструкция (_s или _u).
  • «Нужно использовать i64 для надёжности» — i64 тяжелее на 32-битных платформах; берите i32, если значения помещаются.

Итоги

  • Базовых типов всего четыре: i32, i64, f32, f64.
  • Булево, символы, флаги — это i32; строки и массивы — байты в памяти.
  • Знаковость не в типе, а в инструкции (_s / _u).
  • Минимализм типов даёт простую валидацию и быструю компиляцию.
Проверьте себя
1. Сколько базовых числовых типов в ядре WebAssembly?
AДва
BЧетыре: i32, i64, f32, f64
CВосемь
DСтолько же, сколько в C
2. Как в Wasm обычно представлено булево значение?
AОтдельным типом bool
BКак i32: 0 — ложь, ненулевое — истина
CКак f32
DСтрокой 'true'/'false'
3. Где в Wasm задаётся знаковость числа?
AВ самом типе i32
BВ конкретной инструкции: суффикс _s (signed) или _u (unsigned)
CВ заголовке модуля
DЗнаковости в Wasm нет вообще