Размещение исполняемого файла в ОЗУ в модели large — КиберПедия 

Папиллярные узоры пальцев рук - маркер спортивных способностей: дерматоглифические признаки формируются на 3-5 месяце беременности, не изменяются в течение жизни...

Состав сооружений: решетки и песколовки: Решетки – это первое устройство в схеме очистных сооружений. Они представляют...

Размещение исполняемого файла в ОЗУ в модели large

2020-04-01 101
Размещение исполняемого файла в ОЗУ в модели large 0.00 из 5.00 0 оценок
Заказать работу

 

Модели памяти устроены по-разному. Рассмотрим расположение областей памяти в модели large.

Область кода содержит машинные коды функций программы. Функции, присоединенные к exe-файлу на стадии линковки, размещаются вне области кода.

Область данных содержит глобальные и статические переменные, строковые константы.

В стеке размещаются локальные переменные, параметры, передаваемые функциям, и ряд других данных. Как правило, стек растет сверху вниз, занимая пульсирующую непрерывную область. В случае переполнения стека происходит его "налезание" стека на область данных и выдается соответствующее сообщение. Проверка стека увеличивает время работы программы и ее можно отключить в Options-Entry/Exit Code Generation-Stack options-Test stack overflow.

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


Рис.1. Сегментация для модели памяти Large

 


Передача данных в функцию

 

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

 

[тип возвращаемого значения] имя_функции (список параметров)

{тело функции

[return возвращаемое_значение] }

 

В скобках помещена необязательная часть конструкции.

В списке параметров указывают данные, которые необходимо передать в функцию. Ниже рассмотрены различные способы передачи данных в функцию.

Передача параметров по значению

 

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

Например:

 

void print_num (int i, int j)

{ printf ("значение i=%d. Значение j=%d. ", i,j);}

Обращение в программе к данной функции будет таковым:

print_num (6, 19);


Передача параметров по адресу

 

Рассмотрим пример функции, которая меняет значение переменных местами:

 

void change (int x, int y)

{ int k=x;

x=y;

y=k;

}

 

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

Пример:

 

void change (int *x, int *y)

{ int k=*x;

*x=*y;

*y=k;

}

 

При вызове такой функции в качестве фактических параметров должны быть использованы не значения переменных, а их адреса change (&a,&b);


Передача одномерных массивов

 

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

Пример.

 

int sum (int A [], int Dim); // прототип

int sum (int A [], int Dim); // заголовок

{

….

} // телофункции

void main ()

{

int res, A [] = {2,1,3,2};

res = sum (A,

4);

} // вызов функции sum

 

Формальный аргумент имени массива может иметь вид int *A.

int sum (int *A, int Dim); // прототип

Для определения размера массива при вызове функции можно использовать выражение sizeof (A) /sizeof (int) или sizeof (A) /sizeof (A []). Например,

 

res = sum (A, sizeof (A) /sizeof (A []));

 


Передача двумерных массивов

 

Способ 1. При передаче двумерного массива в функцию следует учитывать, что количество элементов в строке массива является частью типа имени этого массива. Так например, для массива int A [3] [4] имя массива А имеет тип int (*) [4], т.е. А - это указатель на одномерный массив из 4 элементов типа int.

Поэтому необходимо передавать два параметра: имя массива и количество строк в массиве.

Пример.

 

int sum2 (int A [] [4], int M); // прототип

int sum2 (int A [] [4], int M); // заголовок

{

….

} // телофункции

void main ()

{

int res, A [] [4] = {{2,1,3,2}, {2,3,4,5}}; // две строки, четыре столобца

res = sum2 (A,

2); // вызов функции sum2

}

 

Формальный аргумент имени массива может иметь вид int (*A) [4].

int sum2 (int (*A) [4], int M); // прототип

Для определения размера массива при вызове функции можно использовать выражение sizeof (A) /sizeof (A []). Например,

 

res = sum2 (A, sizeof (A) /sizeof (A []));

 

Способ 2. Другой способ передачи двумерного массива в функцию состоит в погружении фактического двумерного массива с размерами MxN в двумерный массив заведомо больших размеров. Пи этом достаточно взять большой размер стоки, например, 100.

 

int sum3 (int A [] [100], int M, int N); // прототип

int sum3 (int A [] [100], int M, int N); // заголовок

{

….

} // телофункции

void main ()

{

int res, A [2] [100] = {{2,1,3,2}, {2,3,4,5}}; /* две строки, четыре столбца с чатичной инициалиазацией*/

res = sum3 (A, 2,4); // вызов функции sum3

}

 

Способ 3. Третий способ передачи двумерного массива в функцию состоит в эмуляции фактического двумерного массива с размерами MxN с помощью одномерного массива с размером M*N. Пи этом M*N должно быть меньше 64К.

 

int sum4 (int A [], int M, int N); // прототип

int sum4 (int A [], int M, int N); // заголовок

{

….

} // телофункции

void main ()

{

int res, A [2] [4] = {{2,1,3,2}, {2,3,4,5}}; /* две строки, четыре столбца */

res = sum4 ((int *) A, 2,4); // вызов функции sum4

}

 


Тестирование функций

 

Вычислительные модули необходимо тщательно протестировать с помощью отдельной тестовой функции с прототипом

void test (void);

При тестировании следует соблюдать следующие требования:

автоматизм, то есть от программиста при тестировании не требуется никаких действий,

прозрачность. Это означает, что функция test выводит сообщения на экран только в случае возникновения ошибок.

иллюстративность: листинг тестовой функции позволяет посмотреть различные способы вызова проверяемой функции.

всесторонность, то есть при тестировании необходимо рассмотреть все крайние ситуации.

В программе должны осуществляться все возможные проверки, в частности:

на корректность входных данных,

при выделении динамической памяти,

на выход индексов массива из диапазона.

 


5. Практические задания

 


Поделиться с друзьями:

Общие условия выбора системы дренажа: Система дренажа выбирается в зависимости от характера защищаемого...

Типы сооружений для обработки осадков: Септиками называются сооружения, в которых одновременно происходят осветление сточной жидкости...

Опора деревянной одностоечной и способы укрепление угловых опор: Опоры ВЛ - конструкции, предназначен­ные для поддерживания проводов на необходимой высоте над землей, водой...

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



© cyberpedia.su 2017-2024 - Не является автором материалов. Исключительное право сохранено за автором текста.
Если вы не хотите, чтобы данный материал был у нас на сайте, перейдите по ссылке: Нарушение авторских прав. Мы поможем в написании вашей работы!

0.018 с.