Хранение массива в памяти

III. Свойства

Классы, перечисленные выше пунктирной линии, описываются внутри функции.
Классы, перечисленные ниже этой линии, определяются вне функции.

Класс памяти Ключевое слово Продолжительность Область деиствия
Автоматический auto Временно Локальная
Статический static Постоянно Локальная
Внешняя extern Постоянно Глобальная (все файлы)
Внешняя статическая static Постоянно Глобальная (один файл)

Компьютерная программа в целом или её отдельная процедура называется реентера?бельной (от англ. reentrant — повторно входимый), если она разработана таким образом, что одна и та же копия инструкций программы в памяти может быть совместно использована несколькими пользователями или процессами. При этом второй пользователь может вызвать реентерабельный код до того, как с ним завершит работу первый пользователь и это как минимум не должно привести к ошибке, а в лучшем случае не должно вызвать потери вычислений (то есть не должно появиться необходимости выполнять уже выполненные фрагменты кода).

Реентерабельность тесно связана с безопасностью функции в многопоточной среде (thread-safety), тем не менее, это разные понятия (в практическом программировании под современные ОС термин «реентерабельный» на деле равносилен термину «thread-safe»). Обеспечение реентерабельности является ключевым моментом при программировании многозадачных систем, в частности, операционных систем.

Для обеспечения реентерабельности необходимо выполнение нескольких условий:

  • никакая часть вызываемого кода не должна модифицироваться;
  • вызываемая процедура не должна сохранять информацию между вызовами;
  • если процедура изменяет какие-либо данные, то они должны быть уникальными для каждого пользователя;
  • процедура не должна возвращать указатели на объекты, общие для разных пользователей.

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

Рекурсивные функции

Ситуацию, когда функция тем или иным образом вызывает саму себя, называют рекурсией. Рекурсия, когда функция обращается сама к себе непосредственно, называется прямой; в противном случае она называется косвенной.

Все функции языка С++ (кроме функции main) могут быть использованы для построения рекурсии.

В рекурсивной функции обязательно должно присутствовать хотя бы одно условие, при выполнении которого последовательность рекурсивных вызовов должна быть прекращена.

18) Массивы предназначены для хранения множества значений одного типа. Например, в программе Fahrenheit to Celsius, мы высчитывали среднее значение температуры из трёх. Если значений не три, а намного больше, то тут как раз и нужно использовать массивы.

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

int array[10];

В этом коде мы определили массив с идентификатором (именем) array (массив) из десяти элементов типа int.

В таком виде, все элементы массива ещё неинициализированы. Чтобы инициализировать их при обьявлении, нужно использовать следующий синтаксис:

int array[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};

Хранение массива в памяти

Элементы массива размещаются в памяти последовательно, друг за другом. Каждый элемент массива занимает столько памяти, сколько отводится под переменную, тип которой указан при описании массива.

Размер массива – это общее количество элементов в массиве. Чаще под размером массива понимают объем памяти, занимаемый массивом – это общее количество элементов в массиве, умноженное на размер одного элемента. Размер, который занимает переменная-массив в памяти можно узнать в программе с использованием конструкции

sizeof(A);

Реальный адрес элемента массива в памяти можно вычислить, зная базовый адрес массива (адрес начала массива), тип элементов массива и номер нужного элемента.

Литеральная константа — это константа (число, строковое выражение, дата), расположенная непосредственно в коде.

Например: X = Y + 2

Здесь число 2 является литеральной константой.

Символьные строки хранят такую информацию, как имена файлов, названия книг, имена служащих и другие символьные сочетания. Большинство программ на C++ широко используют символьные строки. Далее вы узнаете, что в C++ символьные строки хранятся в массиве типаchar, который заканчивается символом NULL (или ASCII 0). В данном уроке символьные строки рассматриваются более подробно. Вы узнаете, как хранить и обрабатывать символьные строки, а также как использовать функции библиотеки этапа выполнения, которые манипулируют символьными строками. К концу этого урока вы освоите следующие основные концепции:

19)Указатель – это переменная, значением которой является адрес некоторого объекта (обычно другой переменной) в памяти компьютера. Подобно тому, как переменная типа char имеет в качестве значения символ, а переменная типа int – целочисленное значение, переменная типа указателя имеет в качестве значения адрес ячейки оперативной памяти. Допустимые значения для переменной-указателя – множество адресов оперативной памяти компьютера.

Указатель является одной из наиболее важных концепций языка C.

Правильное понимание и использование указателей особенно необходимо для составления хороших программ по следующим причинам:

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

Однако указатель может вызвать и ряд затруднений, например, если указатель содержит неправильное значение, программа может быть неработоспособной. Можно легко ошибиться при использовании указателей; к тому же ошибки, связанные с неправильными значениями указателей, найти очень трудно.

Итак, указатель – это новый тип данных. Для него определены понятия константы, переменной, массива. Как и любую переменную, указатель необходимо объявить. Объявление указателя состоит из имени базового типа, символа * (звездочка) и имени переменной.

Общая форма объявления указателя:

тип *имя;

Тип указателя определяет тип объекта, на который указатель будет ссылаться, например,

int *p1;

Фактически указатель любого типа может ссылаться на любое место в памяти, но выполняемые над указателем операции существенно зависят от его типа. Так, если объявлен указатель типа int*, компилятор предполагает, что любой адрес, на который он ссылается, содержит переменную типа int, хотя это может быть и не так. Следовательно, объявляя указатель, необходимо убедиться в том, что его тип совместим с типом объекта, на который он будет ссылаться.

20) Понятия указателей и массивов тесно связаны. Рассмотрим следующий фрагмент программы:

char str[80], *p1;

p1 = str;

Здесь p1 указывает на первый элемент массива str. Обратиться к пятому элементу массива str можно с помощью любого из двух выражений:

str[4]

* (p1+4)

Массив начинается с нуля. Поэтому для пятого элемента массива str нужно использовать индекс 4. Можно также увеличить p1 на 4, тогда он будет указывать на пятый элемент. (Напомним, что имя массива без индекса возвращает адрес первого элемента массива.)

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

21)Указатели на функции[1] — очень мощное средство языка С. Хотя нельзя не отметить, что это весьма трудный для понимания термин. Функция располагается в памяти по определенному адресу, который можно присвоить указателю в качестве его значения. Адресом функции является ее точка входа. Именно этот адрес используется при вызове функции. Так как указатель хранит адрес функции, то она может быть вызвана с помощью этого указателя. Он позволяет также передавать ее другим функциям в качестве аргумента.

Хранение массива в памяти в Си


Похожие статьи.

Понравилась статья? Поделиться с друзьями: