Сырые указатели

В Ü существует тип сырых указателей, подобный (отчасти) таковому во многих низкоуровневых языках, таких, как Си. В Ü сырые указатели синтаксически и функционально несколько отличаются от Си, но главный смысл всё же остаётся.

Сырые указатели предназначены для использования в низкоуровневом коде, таком как код контейнеров, код взаимодействия с другими языками и т. д. Для указателей не работает проверка ссылок, поэтому операция рызыменования указателя дозволена только в unsafe блоках.

Объявляется тип сырого указателя через символ $ и пару круглых скобок, следующих за ним, в которых указывается тип элемента. Примеры:

type i32_ptr = $(i32); // указатель на тип "i32".
type tup_ptr = $(tup[i32, f32]); // указатель на тип кортежа.
type bool_ptr_ptr = $($(bool)); // указатель на указатель на "bool".

Значение типа указателя можно получить из изменяемой ссылки с помощью оператора состоящего из лексемы $< и пары круглых скобок с выражением внутри. Получение ссылки из указателя выполняется с помощью обратного оператора, начинающегося с лексемы $>.

var i32 mut x= 0;
var (i32) x_ptr = $<(x); // Преобразование ссылки на "x" в сырой указатель.
unsafe{  $>(x_ptr) = 24;  } // Разыменование указателя и присвоение значения полученной ссылке. Дозволено только в "unsafe" коде.

Стоит отметить, что в Ü, в отличие от C++ нету модификаторов изменяемости у типов указателей. Все указатели считаются указывающими на изменяемые данные. Поэтому указатель можно получить только из изменяемой ссылки и оператор разыменования указателя возвращает изменяемую ссылку.

Указатель можно инициализировать zero_init инициализатором, в таком случае указатель будет должным образом занулён.

Арифметика указателей

В Ü существует возможность осуществлять арифметические операциями с указателями. Возможны следующие операции:

  • Сложение указателя с целым числом. Разрешено сложение с целыми знаковыми и беззнаковыми числами, но с размером не большим размера указателя. Возможно сложение как указателя с числом, так и числа с указателем (операция сложения коммутативна). Существует оператор += для указателя и числа. Результатом сложения указателя и числа является указатель, указывающий на адрес, больший оригинального на переданное число, помноженное на размер типа элемента указателя.
  • Вычитание целого числа из указателя. Разрешено вычитание целего числа (знакового или беззнакового) из указателя. Размер целого числа должен быть не больше размера указателя. Существует оператор -= для указателя и числа. Результатом вычитания числа из указателя является указатель, указывающий на адрес, меньший оригинального на переданное число, помноженное на размер типа элемента указателя.
  • Разность указателей. Разрешено вычислять разность указателей через оператор -. Тип элемента указателя при этом должен иметь ненулевой размер. Результатом разности указателей является целое знаковое число типа ssize_type, равное разнице значений указателей, делённой на размер типа элемента указателя.
  • Инкремент и декремент. Для указателей возможно использование ++ и --. Значение указателя будет увеличено или уменьшено на размер типа элемента.
  • Сравнение указателей. Все операторы сравнения - ==, !=, <, <=, >, >= применимы к указателям.

Примеры:

var [ i32, 8 ] mut arr= zero_init;
var $(i32) ptr0= $<(a[0]);

auto ptr3 = ptr0 + 3; // ptr3 указывает на arr[3]
auto ptr4 = 4 + ptr0; // ptr4 указывает на arr[4]

auto diff5_2 = $<(a[5]) - $<(a[2]); // diff = 3
auto diff1_6 = $<(a[1]) - $<(a[6]); // diff = -5

auto mut ptr = $<(a[2]); // ptr указывает на arr[2]
++ptr; // ptr теперь указывает на arr[3]
ptr+= 3; // ptr теперь указывает на arr[6]
--ptr; // ptr теперь указывает на arr[5]
ptr-= 4; // ptr теперь указывает на arr[1]

auto is_3_less_4 = ptr3 < prt4; // true
auto is_3_greater_0 = ptr3 > prt0; // true
auto is_3_equal_4 = ptr3 == prt4; // false
auto is_4_less_or_equal_4 = ptr4 <= ptr4; // true