|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
Основы Delphi: 4. Операции над целыми числами Целочисленные типы данных играют ключевую роль в создании любой программы, которая будет выполняться микропроцессором. Основные регистры процессора - целочисленные, а большинство команд работают именно с этими регистрами. Поэтому очень важно эффективно использовать операции над целыми числами. Большинство компиляторов уже имеют средства, позволяющие генерировать оптимальный код, однако программист должен рационально использовать операции над целыми числами и не создавать лишних действий в программе. 32-битный микропроцессор оптимально работает с 32-битными значениями, поэтому в языке Delphi рекомендуется использовать типы integer и cardinal для операций с целыми числами. Однако, остальные целочисленные типы также могут быть использованы, если необходимо особым образом определить некую область памяти. Целочисленные типы Далее представлены все целочисленные типы языка Delphi. В таблице указано сколько памяти занимает значение того или иного типа:
Для того, чтобы определить в программе, сколько памяти занимает тот или иной тип, можно использовать функцию SizeOf: program TypeSize;
{$APPTYPE CONSOLE} begin WriteLn('byte: ',SizeOf(byte)); WriteLn('word: ',SizeOf(word)); WriteLn('cardinal: ',SizeOf(cardinal)); WriteLn('uint64: ',SizeOf(uint64)); ReadLn; end. byte: 1
word: 2 cardinal: 4 uint64: 8 Структура целочисленного значения Для типа byte со структурой все понятно: занимает один байт, от 0 до 255, т.е. от 00000000 до 11111111 в двоичном виде. В структуре числа нет информации о знаке числа, поэтому тип и называется - беззнаковый. Для знакового типа shortint необходимо сохранять информацию о знаке - для этого достаточно одного старшего (первого слева) бита. Если он равен 0, то число - положительное (или равное нулю) и его значения варьируются от 0 до 127, т.е. от 00000000 до 01111111. Если старший бит равен 1, то число - отрицательно, и оставшиеся 7 бит являются разностью между числом 128 и модулем искомого числа (так называемый дополнительный код числа). Например:
Остальные целочисленные типы требуют больше, чем 1 байт памяти. Для удобства байты значения в памяти записывают в обратном порядке. Например число 123456 типа integer, которое в двоичном и шестнадцатиричном виде записывается как 00000000000000011110001001000000 0001E240 в памяти будет представлено в виде 01000000 11100010 00000001 00000000 40 E2 01 00 Чтобы убедиться в том, что байты значения в памяти записываются в обратном порядке можно провести эксперимент. Возьмем у числа 789 (или 0000001100010101) типа word только первый байт, и он должен равняться 21 (или 00010101), а не 3 (или 00000011) при прямом порядке: program ByteOrder;
{$APPTYPE CONSOLE} var A: word; P: pointer; begin A := 789; P := @A; // указатель на область памяти переменной A WriteLn( A ); WriteLn( PByte(P)^ ); // выводим первый байт области памяти // на который указывает P ReadLn; end. 789
21 Операции Операции над целыми числами можно разделить на арифметические и побитовые. Арифметические операции представлены в следующей таблице:
Побитовые (bitwise) операции отличаются от арифметических тем, что взаимодействуют не сами числа, а соответствующие биты. Для каждой пары битов выполняется какая-либо логическая операция, и результат побитовой операции будет составляться из результатов логических операций для каждой пары бит.
Приведение типов Значения одного целочисленного типа приводятся к другому целочисленному типу без каких либо проблем. Следует учесть, что если новый тип занимает в памяти меньше байт, чем старый тип, то лишние байты просто отсекаются. Это также удобно, если необходимо получить первые несколько байт целочисленного значение (например, первый байт значения типа word или первые два байта значения типа cardinal). Однако, если тип значения знаковый, а само значение отрицательное, то приведение к типу, занимающему меньше памяти, может привести к положительному результату. Например, приводя значение -1000 (11111100 00011000) типа smallint к типу shortint, в результате получим 24 (00011000). Значение результата какой-либо целочисленной операции всегда имеет тип, который занимает в памяти максимум из типов операндов. Например, integer + word = integer, int64 - byte = int64. Это может создать проблемы при операции умножения, когда результат необходимо получить с типом int64. В конструкции var
a, b: integer; c: int64; ... c := a * b; выражение (a * b) имеет тип integer, а не int64, и значение может переполниться. В этом случае следует привести один из операндов к типу int64. Явное приведение к какому-либо типу описывается следующим образом: <тип> ( <выражение> ) В таком случае, текст программы выглядит так: var
a, b: integer; c: int64; ... c := int64(a) * b; |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|