Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
CSharp Language Specification.doc
Скачиваний:
12
Добавлен:
26.09.2019
Размер:
4.75 Mб
Скачать

18.5.4Оператор адреса

Выражение_адрес состоит из амперсанда (&), за которым следует унарное_выражение.

выражение_addressof: & унарное_выражение

Если дано выражение E типа T и классифицируемое как фиксированная переменная (§18.3), конструкция &E вычисляет адрес переменной, заданной выражением E. Типом результата является T*, классифицируемый как значение. Вызывается ошибка времени компиляции, если E не классифицируется как переменная, если E классифицируется как локальная переменная только для чтения или если E обозначает перемещаемую переменную. В этом последнем случае можно использовать оператор fixed (§18.6), чтобы временно «фиксировать» переменную перед получением ее адреса. Как изложено в §7.6.4, вне конструктора экземпляров или статического конструктора для структуры или класса, определяющего поле readonly, это поле считается значением, а не переменной. Его адрес, как таковой, нельзя получить. Аналогично и адрес константы получить нельзя.

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

В этом примере

using System;

class Test { static void Main() { int i; unsafe { int* p = &i; *p = 123; } Console.WriteLine(i); } }

i считается определенно присвоенным после операции &i, использованной для инициализации p. Присваивание для *p в сущности инициализирует i, но включение этой инициализации является обязанностью программиста, и если удалить это присваивание, ошибки времени компиляции не будет.

Правила определенного присваивания для оператора & таковы, что можно избежать избыточной инициализации локальных переменных. Например, многие внешние API принимают указатель на структуру, заполненную посредством API. При вызове таких API обычно передается адрес локальной переменной типа структуры, и без этого правила потребовалась бы избыточная инициализация переменной типа структуры.

18.5.5Увеличение и уменьшение указателя

В небезопасном контексте операторы ++ и ‑‑ (§7.6.9 и §7.7.5) могут применяться к переменным типа указателя всех типов, кроме void*. Так, для каждого типа указателя T* неявно определены следующие операторы:

T* operator ++(T* x);

T* operator --(T* x);

Эти операторы дают такой же результат, как x + 1 и x - 1, соответственно (§18.5.6). Иначе говоря, для переменной типа указателя с типом T* оператор ++ добавляет sizeof(T) к адресу, содержащемуся в переменной, а оператор ‑‑ вычитает sizeof(T) из адреса, содержащегося в переменной.

Если при операциях увеличения или уменьшения указателя переполняется область типа указателя, результат зависит от реализации, но исключения не создаются.

18.5.6Арифметические операции с указателем

В небезопасном контексте операторы + и - (§7.8.4 и §7.8.5) могут применяться к значениям всех типов указателей, кроме void*. Так, для каждого типа указателя T* неявно определены следующие операторы:

T* operator +(T* x, int y); T* operator +(T* x, uint y); T* operator +(T* x, long y); T* operator +(T* x, ulong y);

T* operator +(int x, T* y); T* operator +(uint x, T* y); T* operator +(long x, T* y); T* operator +(ulong x, T* y);

T* operator –(T* x, int y); T* operator –(T* x, uint y); T* operator –(T* x, long y); T* operator –(T* x, ulong y);

long operator –(T* x, T* y);

Если дано выражение P типа указателя T* и выражение N типа int, uint, long или ulong, то выражения P + N и N + P вычисляют значение указателя типа T*, получающееся при добавлении N * sizeof(T) к адресу, заданному выражением P. Аналогично выражение P - N вычисляет значение указателя типа T*, получающееся при вычитании N * sizeof(T) из адреса, заданного выражением P.

Если даны два выражения, P и Q, типа указателя T*, то выражение P – Q вычисляет разность адресов, заданных P и Q, а затем делит эту разность на sizeof(T). Тип результата всегда long. В сущности, P - Q вычисляется как ((long)(P) - (long)(Q)) / sizeof(T).

Пример:

using System;

class Test {

static void Main() { unsafe { int* values = stackalloc int[20]; int* p = &values[1]; int* q = &values[15]; Console.WriteLine("p - q = {0}", p - q); Console.WriteLine("q - p = {0}", q - p); } } }

В результате получается:

p - q = -14 q - p = 14

Если при арифметических операциях с указателем переполняется область типа указателя, результат усекается способом, зависящим от реализации, но исключения не создаются.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]