Шаг 207.
Язык программирования C#. Начала.
Указатели. Адресная арифметика

    На этом шаге мы рассмотрим особенности выполнения такой арифметики.

    На предыдущих шагах мы видели, что адрес - это целое число. Мы можем представлять себе одномерную последовательность ячеек (хотя в действительности все намного сложнее - но в данном случае это не важно), каждая размером в 1 байт. У каждой ячейки есть адрес (целое число). Будем исходить из того, что адрес увеличивается справа налево. Адреса соседних ячеек отличаются на 1. Если имеется некоторая ячейка с адресом, то соседняя ячейка справа имеет адрес на единицу меньше, а соседняя ячейка слева имеет адрес на единицу больше. Для записи значений может использоваться несколько ячеек (будем называть это блоком) - все зависит от типа значения. Например, значение типа double занимает 8 ячеек, значение типа int занимает 4 ячейки, значение типа char занимает 2 ячейки, а значение типа byte занимает 1 ячейку. То есть для записи значений разных типов используются блоки памяти разного размера. В указатель при этом записывается адрес первой ячейки в блоке. Поэтому если в памяти подряд размещено два значения типа byte, то адреса блоков, в которые записаны эти значения, будут отличаться на 1. Если рядом в памяти два блока с int-значениями, то адреса этих блоков отличаются на 4. Адреса соседних double-блоков отличаются на 8. Таким образом, дискретность изменения адресов соседних блоков памяти определяется типом значений, которые записаны в эти блоки.


Здесь приводятся объемы памяти, которые должны выделяться для значений разных типов по стандарту языка C#. Узнать фактический объем памяти (в байтах), выделяемый компилятором под значение определенного типа, можно с помощью инструкции sizeof. Например, результатом выражения sizeof(int) является целое число, равное количеству байтов, выделяемых для значения типа int (должно быть равно 4). Значение выражения sizeof(char) - объем памяти (в байтах), выделяемый для значения типа char (по стандарту должно быть 2).

    Считывание значения из области памяти и запись в область памяти значения с использованием указателей - далеко не единственные поддерживаемые в C# операции. Есть группа важных и полезных операций, которые могут выполняться с указателями.


Далее под ячейкой будет подразумеваться однобайтовый блок, а под блоком в общем случае мы будем подразумевать группу из нескольких ячеек. Фраза "указатель ссылается на ячейку" понимается в том смысле, что указатель содержит адрес соответствующей ячейки в качестве значения.

    Перечисленные выше правила имеют простые и очевидные последствия. Например, если указатели (одного типа) ссылаются на соседние блоки, то разность этих указателей равна 1 или -1, в зависимости от того, как относительно друг друга расположены блоки. При этом разность адресов, записанных в указатели, отличается на значение, равное объему (в байтах) блока памяти, выделяемого для записи значения данного типа. Далее, если p - некоторый указатель, то p[0] - значение, записанное в блоке, на который ссылается p (то есть то же, что и *p). Значениями выражений p+1 и p-1 являются адреса блоков, соседних с блоком, на который ссылается указатель p. Если k - целое число, то выражение p[k] эквивалентно выражению *(p+k), и так далее (таких интересных соотношений довольно много).

    На следующем шаге мы продолжим изучение этого вопроса.




Предыдущий шаг Содержание Следующий шаг