Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Programmirovanie_bilety_1kurs_2semestr.docx
Скачиваний:
2
Добавлен:
23.09.2019
Размер:
339.12 Кб
Скачать

Программирование.билеты.2 семестр.1 курс.

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

Инициализация (от англ. initialization, инициирование) — создание, активация, подготовка к работе, определение параметров. Приведение программы или устройства в состояние готовности к использованию.

Переменная - это объект, который способен хранить в себе значение определенного типа.

1. Структура магнитного носителя. Понятие сектора, чередования секторов. Для чего нужно чередование секторов. Кластер.

Структура магнитного носителя: Физическая структура, логическая структура. Логическая структура гибких дисков: представляет собой совокупность секторов (емкостью 512 байтов), каждый из которых имеет свой порядковый номер. Сектора нумеруются в линейной последовательности от первого сектора нулевой дорожки до последнего сектора последней дорожки. Формирование физической структуры диска состоит в создании на диске концентрических дорожек, которые в свою очередь, делятся на секторы. У гибкого диска две стороны, на которых создается по 80 дорожек. На каждой дорожке по 18 секторов. Объем каждого сектора 512 байтов. Следовательно, объем гибкого диска = (2∙80∙18∙512) байт = 1474560 байт = 1140 Кбайт = 1,44 Мбайт. Сектор, чередование секторов: Обычно сектора на дорожке располагаются по возрастанию порядковых номеров. Если программа будет читать несколько секторов с последовательными номерами(она обычно так и делает) на чтение каждого сектора уйдет время будет затрачено время, равное времени оборота диска. Чтобы улучшить временные характеристики можно расположить секторы через 1. Когда секторы располагаются последовательно в порядке возрастания их номеров, фактор чередования секторов равен 1. Когда чередуются через один - фактор чередования равен 2. В таком случае после чтения одного сектора будет достаточно времени для чтения следующего и вся дорожка может быть считана за 2 оборота. Кластер – это несколько следующих друг за другом секторов дискового пространства (по умолчанию объем каждого физического сектора – 512 байт). Размер кластера зависит от общей емкости накопителя на магнитном диске. Если объем информации в файле превышает объем одного кластера, то следующая порция данных располагается на ближайшем свободном кластере, который физически может не быть смежным с первой порцией данных. Таким образом, большой набор данных оказывается разбросанным по разным не обязательно соседним участкам диска.

2. Понятие файловой системы. Кластер. Файла. Фрагментированный файл. Что такое дефрагментация. Как можно уменьшить потери при хранении файлов? Файловая система- это часть операционной системы, назначение которой состоит в том, чтобы обеспечить пользователю удобный интерфейс при работе с данными, хранящимися на диске, и обеспечить совместное использование файлов несколькими пользователями и процессами. В широком смысле файловая система включает совокупность всех файлов на диске, набор структур данных, используемых для управления файлами, комплекс системных программных средств, реализующих управления файлами. Кластер – это несколько следующих друг за другом секторов дискового пространства (по умолчанию объем каждого физического сектора – 512 байт). Размер кластера зависит от общей емкости накопителя на магнитном диске. Если объем информации в файле превышает объем одного кластера, то следующая порция данных располагается на ближайшем свободном кластере, который физически может не быть смежным с первой порцией данных. Таким образом, большой набор данных оказывается разбросанным по разным не обязательно соседним участкам диска. Минимальной единицей хранения является файл – набор данных, снабженных следующей информацией: имя файла, расширение имени, дата и время создания, длина в байтах, атрибуты, ссылка на начало данных(логическое представление файла). Фрагментированный файл: различные фрагменты одного и того же файла при записи могут оказаться расположенными не последовательно, а в разных областях дискового пространства. В итоге файлы становятся фрагментированными, то есть разбитыми на множество отдельных фрагментов. Дефрагментация - это процесс обновления и оптимизации логической структуры раздела диска с целью обеспечить хранение файлов в непрерывной последовательности кластеров. Дефрагментация представляет собой процесс реорганизации способа хранения файлов, в результате которого отдельные части одного файла, по возможности размещаются последовательно одним блоком. Это приводит к увеличению скорости доступа к файлам (они быстрее загружаются), а значит, к некоторому повышению общего быстродействия компьютера, что при высоком уровне фрагментированности будет довольно заметным. Чем больше размер кластера, тем больше потери, но тем быстрее работает файловая система и занимает меньше места в памяти Чем меньше размер кластера, тем меньше потери при хранении файлов, то тем медленнее работает файловая система, и тем больше занимает места на диске и в оперативной памяти. Поэтому всегда ищется оптимальный размер кластера. 3. Логическое представление файла. Физическое представление файла. Работа с файлами. Понятие интерфейса. Что такое интерфейс для работы с файлами на уровне языка программирования и на уровне ОС. Возможно ли существование нескольких интерфейсов в одном языке программирования для работы с файлами.Логическое представление файла: файл - это одна из многих структур данных, используемых в программировании. Файл в таком понимании называют логическим файлом, то есть существующим только в нашем логическом представлении при написании программы. В программах логические файлы представляются файловыми переменными определенного типа. Структура логического файла - это способ восприятия файла в программе. Имя файла, состоящее из букв латинского алфавита, цифр и некоторых символов; расширением имени, отделяемое от имени точкой и содержащее обычно 3 символа; дата и время создания файла, длина в байтах, атрибуты файла, ссылка на начало данных- адрес первого кластера, с которого на диске расположена информация содержимого файла.

Физическое представления файла имеет дело с тем, как и где данные физически размещаются и хранятся на дисках, магнитных лентах и других носителях. Интерфейс- разновидность интерфейсов, в котором одна сторона представлена человеком (пользователем), другая — машиной/устройством. Представляет собой совокупность средств и методов, при помощи которых пользователь взаимодействует с различными, чаще всего сложными, машинами, устройствами и аппаратурой. Программист знает только набор функций для работы с файлами на языке программирования, программисту нет необходимости знать интерфейс работы с файлами для каждой ос. Написанная программа переносима с одной ос на другую, практически без изменения кода программы с условием перекомпиляции. Может существовать несколько интерфейсов для работы с файлами на языке программирования. 4. Логическое и физическое представление файла. Понятие интерфейса. Интерфейсы работы с файлами в СИ. Описание stdio.h. Какие бывают фалы по содержимому в stdio.h. Логическое представление имеет дело с тем, как пользователи организуют, просматривают, понимают данные и их отношения. Физическое представление имеет дело с тем, как и где данные физически размещаются и хранятся на дисках, магнитных лентах и других носителях. Отделение способа использования данных от того, как они хранятся и выбираются означает, что пользователи могут менять свое логическое представление, не делая изменений в физическом представлении. Интерфейс- совокупность средств и правил обеспечивающих взаимодействие устройств вычислительной системы и программ, а также взаимодействие их с человеком. Логическое представление: имя файла, состоящее из букв латинского алфавита, цифр и некоторых символов; расширение имени, отделяемое от имени точкой и содержащее обычно 3 символа; дата и время создания файла или момента его последней модификации; длина файла в байтах; атрибуты файла (A – архивируемый, R – только для чтения, S – системный, H – скрытый); ссылка на начало данных – адрес первого кластера, с которого на диске расположена первая порция информационного содержимого файла. Физическое представление (может быть не то): Заголовок файла растровой графики (14 байт) Сигнатура файла BMP (2 байт) Размер файла (4 байт) Не используется (2 байт) Не используется (2 байт) Местонахождение данных растрового массива (4 байт) Информационный заголовок растрового массива (40 байт) Длина этого заголовка (4 байт) Ширина изображения (4 байт) Высота изображения (4 байт) Число цветовых плоскостей (2 байт) Бит/пиксель (2 байт) Метод сжатия (4 байт) Длина растрового массива (4 байт) Горизонтальное разрешение (4 байт) Вертикальное разрешение (4 байт) Число цветов изображения (4 байт) Число основных цветов (4 байт)

Интерфейс программирования (иногда интерфейс прикладного программирования) — набор готовых классов, процедур, функций, структур и констант, предоставляемых приложением (библиотекой, сервисом) для использования во внешних программных продуктах. Программисту нет необходимости знать интерфейс работы с файлами для каждой ОС Программист знает только набор функций для работы с файлами только на его любимом языке программирования Написанная программа переносима с одной ОС на другую, практически без изменения кода программы, но с перекомпиляцией .

Интерфейсы работы с файлами в СИ: stdio.h классический интерфейс для работы с файлами std-standart стандарт i-input-ввод o-output вывод (стандартный ввод/вывод) Открыть файл fopen () Считать с файла fread() Записать в файл fwrite() Закрыть файл fclose() fstream.h- потоковый интерфейс для работы с файлами Какие бывают фалы по содержимому в stdio.h: текстовые и бинарные . Двоичный (бинарный) файл — в широком смысле: последовательность произвольных байтов. Название связано с тем, что байты состоят из бит, то есть двоичных (англ. binary) цифр. В узком смысле слова двоичные файлы противопоставляются текстовым файлам. При этом с точки зрения технической реализации на уровне аппаратуры, текстовые файлы являются частным случаем двоичных файлов, и, таким образом, в широком значении слова под определение «двоичный файл» подходит любой файл. Описание stdio.h . Стандартный ввод/вывод, заголовочный файл стандартной библиотеки языка Си, содержащий определения макросов, константы и объявления функций и типов, используемых для различных операций стандартного ввода и вывода. Какие бывают файлы по содержимому в stdio.h. Текстовые и бинарные. Текстовые. 5. Работа с текстовыми файлами в stdio.h. Как создать новый пустой текстовый файл (пример). Как проверить корректность открытия или создания файла. Работа с текстовыми файлами в stdio.h. Для работы с файлами в языке С++ имеется набор функций, определенных в библиотеке stdio.h. Перед началом работы с файлом его следует открыть, что достигается с помощью функции fopen(), имеющий следующий синтаксис -FILE *fopen( const char *filename, const char *mode ); Здесь filename – строка, содержащая путь и имя файла; mode – строка, определяющая режим открытия файла: на чтение или на запись; FILE – специальный тип данных для работы с файлами. Данная функция возвращает значение NULL, если файл не был успешно открыт, иначе – другое значение. Рассмотрим последовательность действий по созданию простого текстового файла на языке C++ и записи в него текстовой информации. Если файл существует и его возможно открыть, то создается описание файла типа (FILE) и функция fopen возвращает адрес структуры FILE При записи в файл нескольких чисел, обязательно разделяйте их пробелами FILE *f1; f1=fopen(имя_файла, "режим"); режимы: "rt" – read text - текстовый для чтения "wt" – write text - текстовый для записи "at" – append text -текстовый для дозаписи в уже существующий набор данных Запись в файл – печать в файл - fprintf анологично функчии printf #include "stdio.h" #include "stdlib.h" int main() { FILE *f1; f1 = fopen("testfile.txt","wt"); fprintf(f1,"I live in Chelybinsk"); fclose(f1); } Как создать новый пустой текстовый файл (пример) #include "stdio.h" #include "stdlib.h" int main() { FILE *f1; f1 = fopen("myfile.txt","wt"); fclose(f1); } Как проверить корректность открытия или создания файла. Если файл НЕ существует и его НЕ возможно открыть, то объект типа FILE не создается и адрес будет NULL=0; FILE *f1; f1 = fopen("ttt.txt","rt"); if (f!=NULL)-вот она проверка моей мечты {

6. Функции для работы с текстовыми файлами. Примеры c int, char и float. Запись в файл-печать в файл-fprintf Функция: посылает форматированный вывод в поток Файл, содержащий прототип: stdio.h Описание: fprintf получает набор аргументов, по одному для каждой спецификации формата, и выводит данные в поток. Количество аргументов должно совпадать с числом спецификаций. Описание спецификаций формата приведено в описании функции printf. Возвращение значение: fprintf возвращает число выведенных байт. При появлении ошибки возвращает EOF. Пример: #include "stdio.h" #include "stdlib.h" int main() { FILE *f1; f1 = fopen("testfile.txt","wt"); fprintf(f1,"This is my file!!!"); fclose(f1); } В некоторых случаях, все что записывали в файл, не может не сохранится без fclose. fputs - запись строки в файл Описание: записывает строку 's', исключая завершающую литеру О, в поток fp Использование #include <stdio.h> int fputs(char *s, FILE *fp); /* ANSI */ Возвращаемое значение: возвращает 0 в случае успеха и не 0 при ошибке записи. Пример Код: #include <stdio.h> main() { if (fputs("Hello World\n", stdout)==-1) fprintf(stderr, "Ошибка вывода\n"); } fgets - взять строку из файла Описание: считывает литеры из потока fp в строку по указателю str. Чтение заканчивается, когда встречается литера `\n' (новая строка), конец файла, возникает ошибка чтения или число прочитанных литер достигает n-1. Строка завершается 0. Литера '\n' (новая строка) включается в строку (перед 0). Использование: #include <stdio.h> char *fgets(char *str, int n, FILE *fp); /* ANSI */ Возвращаемое значение: возвращает строку str в случае успеха. Если не было прочитано ни одной литеры и произошла ошибка чтения или встречен EOF, возвращает NULL, а строка str остается без изменения. Если возникла ошибка при чтении, возвращает NULL, а в строке возможен мусор. Пример: Код: #include <stdio.h> main() { char buffer[225]; int buflen; char *result; buflen=255; fputs("Введите строку данных\n", stdout); result=fgets(buffer, buflen, stdin); if (!result) printf("\n конец файла (EOF) или ошибка (ERROR)\n"); else fputs(buffer, stdout); } int fscanf (stream, format-string [, argument ...]); FILE *stream; указатель на структуру FILE. char *format-string; строка управления форматом. Описание: функция fscanf считывает данные из текущей позиции потока stream в место, определяемое заданием аргументов arguments (если они есть). Каждый аргумент должен быть указателем на переменную и тип, которые соответствуют типу, заданному в строке формата. Строка формата управляет интерпретацией полей ввода и имеет ту же самую форму и назначение, что и аргумент строки формата для функции scanf. (Описание функции scanf приводится ниже в данной части руководства). Возвращаемое значение: данная функция возвращает число удачно преобразованных и правильно назначенных полей. Возвращаемое значение не включает полей, прочитанных, но не назначенных. При попытке считывания конца файла возвращается значение EOF. Возвращаемое значение 0 обозначает, что нет назначенных полей. Чтение из файла-сканирование файлов-fscanf int fscanf (stream,format-string[,argument…]); FILE*stream; указатель на структуру FILE. Char*format-string; строка управления форматом. Функция fscanf считывает данные из текущей позиции потока (файла) stream в место, определяемое заданием аргументов arguments (если они есть). Каждый аргумент должен быть указателем на переменную и тип, который соответствует типу, заданному в строке формата.

7. Бинарный файла и stdio.h. основные отличия текстового файла от бинарного. Список функция для работы с бинарными файлами. Бинарный файл - произвольная последовательность байтов. В отличие от текстовых файлов, где доступ последовательный, они используют прямой доступ, так что вы всегда имеете возможность обратиться к любому байту файла. В текстовом файле в отличие от бинарного файла могут присутствовать только печатные символы и некоторые невидимые управляющие символы. Не советуется открывать бинарный файл в текстовом режиме и наоборот, потому что могут быть испорчены форматирование и сама структура файла. Т.е. если читать текстовый файл как бинарный, то тогда вам придется учитывать управляющие символы и как то их пропускать. А если вы откроете бинарный как текстовый, то просто получите непонятную тарабарщину, потому что последовательность байт преобразуется по особым правилам в текст, который не будет иметь никакого смысла.

Открыть файл (fopen) Считать из файл (fscanf) Записать в файл (fprintf) Закрыть файл (fclose)

8. Функция позиционирования внутри бинарного файла (stdio.h). Подробное описание функции с примерами. Позиционированное внутри файла Fseek(f1,delta,pos); F1-указатель на блок управления файлом; Delta -величина смещения в байтах, на которую следует переместить указатель файла; Pos-позиция, от которой производится смещения указатель(0 или SEEK_SET от начала файла, 1 или SEEK_CUR От текущей позиции, 2 или SEEK_END от конца файла). Запись в бинарный файл: #include "stdafx.h" #include "stdio.h" #include "stdlib.h" int main() { FILE *f; if (f=fopen("ttt.bin","wb")) { int i=10; fwrite(&i,sizeof(int),1,f); fclose(f); } scanf(" "); } Fseek - позиционировать файл Описание: устанавливает позицию в файле, связанном с поток fp. Смещение в байтах является величиной со знаком и берется относительно origin определены в io.h файле: SEEK_SET - начало файла SEEK_CUR - текущая позиция SEEK_END - конец файла Если файл открыт в текстовом режиме, смещение может быть только значением, возвращенным ftell, а origin должно быть 0, или offset должно быть 0. Если непосредственно перед вызовом fseek работала ungetс, её результаты теряются. Если файл был открыт в режиме чтения\записи, следом за fseek можно выполнить чтение или запись. Использование: #include <stdio.h> #include <io.h> int fseek(FILE *fp,long offset,int origin); /* ANSI */ Возвращаемое значение: возвращает 0 в случае успеха и ненулевое значение в случае ошибки. Пример: #include <stdio.h> #include <io.h> main() { FILE *fp; fp = fopen("file.dat", "r+"); fseek(fp, 0L, SEEK_END); /* Перейти в конец файла */ fseek(fp, 0L, SEEK_SET); /* Перейти в начало файла */ fseek(fp, 20L, SEEK_SET); /* Перейти на смещение 200 */ }

9. Функция чтения из бинарного файла. Подробное описание функции с примерами (считать высоту и ширину картинки в BMP файле). Чтение двоичного (бинарного) файла осуществляется функцией fread(). Данной функции нужно передать всего два параметра - идентификатор файла и количество символов, которое нужно прочитать. Функция возвращает строку, в которой будут прочитанные символы. Если в качестве параметра функции будет указано большее число символов, чем есть в файле, то ошибки не будет - просто будет выведено все, что есть. include  int fread (buffer, size, count, stream); char *buffer; память для размещения данных. int size; размер в байтах. int count; максимальное число объектов для чтения. FILE *stream; указатель на структуру FILE. Описание: Данная функция читает объекты размера size по счетчику count из входного потока stream и располагает их в буфере buffer. Указатель на файл, связанный с потоком stream (если он есть), увеличивается на число прочитанных байтов. Если выбранный поток открыт в текстовом режиме, комбинация "ВК - ПС" заменяется на символ "ПС". Эта замена не влияет ни на указатель на файл, ни на возвращаемое значение. Возвращаемое значение: Функция fread возвращает число действительно прочитанных объектов, которое меньше, чем count, если при чтении возникла ошибка или встретился конец файла. Пример: #include  FILE *stream; long list[100]; int numread; stream = fopen("data", "r+b"); /* следующий оператор позволяет считать 100 двоичных длинных целых из потока stream */ numread = fread((char *)list, sizeof(long), 100, stream);.

10. Функция записи в бинарный файл. Подробное описание функции с примерами (. Примеры c int, char и массив). Описание 1-ого аргумента- буфер. fwrite-записывает данные из данного буфера в поток; fwrite (const void*p, size_t size,size_t n,FILE*f); Функция записывает n элементов длиной size байт из буфера, заданного указателем p,в поток f. Возвращает число записанных элементов. #include "stdafx.h" #include "stdio.h" #include "stdlib.h" int main() { FILE *f; if (f=fopen("ttt.bin","wb")) { int i=10; fwrite(&i,sizeof(int),1,f); fclose(f); } scanf(" "); } size_t fwrite(const void *ptr, size_t size, size_t n, FILE *stream); Функция fwrite записывает в поток stream данные из массива ptr, длина которого - n элемнтов, а размер каждого элемента - size. Функция возвращает общий объем данных, которые были записаны в поток.

11. Кэш память.

КЭШ - промежуточный буфер с быстрым доступом, содержащий информацию, которая может быть запрошена с наибольшей вероятностью. Доступ к

данным в кэше идёт быстрее, чем выборка исходных данных из оперативной (ОЗУ) и быстрее внешней (жёсткий диск или твердотельный накопитель)

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

КЭШ – прозрачен для программ

КЭШ – работает на большей частоте

КЭШ – хранит часто используемые данные

Эффективность кэша зависит от:

Объёма кэша (Чем больше размер Кэш-памяти, тем больше кэш-попадание)

  • Алгоритма функционирования кэша (Операция чтения, операция записи)

  • Алгоритма функционирования кэша

Эффективность кэша = Количество попаданий в кэш от общего кол-ва обращений к памяти.

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

кэш-памятью первого уровня. Это самая быстрая память.

Данные, которые требуются часто, переносятся на уровень быстрой памяти, называемой кэш-памятью второго уровня.

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

обращается к кэш-памяти первого уровня, а затем — к кэш-памяти второго уровня. Если данных нет ни в одной кэш-памяти, процессор обращается к

оперативной памяти. И только в том случае, если нужных данных нет и там, он считывает данные с жесткого диска.

Когда процессор обнаруживает данные в одном из кэшей, это называют «попаданием»; неудачу называют «промахом». Каждый промах вызывает

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

программными алгоритмами, которые выполняют предварительную выборку данных до того, как они потребуются, процент «попаданий» может достигать 90.

12. Автоматическое и динамическое распределение памяти. Плюсы и минусы каждого из видов распределения памяти.

Автоматический способ выделения памяти.

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

(используется если на момент написания программы точно известен тип данных, под которые выделяется память и объем выделяемой памяти. Этот вид памяти часто называют “статической” памятью. Хотя, если быть более точным, то статическое выделение памяти – это глобальное выделение памяти, когда созданная переменная существует от начала запуска программы до окончания программы. А переменные, объявленные внутри функций, блоков, правильнее называть автоматическими.)

  • Транслятор непосредственно генерирует значения адреса для всех элементов данных

  • Распределение остается неизменным во время исполнения программы

  • Распределение памяти производится во время трансляции

А следовательно можно выделить -

Плюсы:

  • простота реализации и отсутствие накладных расходов для управления памятью во время работы программы (работает быстрее).

Минусы:

  • неэффективное использование памяти

  • несовместим с рекурсивным вызовом подпрограмм

Динамическое распределение памяти из кучи (heap).

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

Или Динамическое распределение памяти — способ выделения оперативной памяти компьютера для объектов в программе, при котором выделение памяти под объект осуществляется во время выполнения программы.

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

Преимущества динам. распределения:

  • Гибкость использования

  • Часто бывает удобно создать новый объект, который существует до тех пор, пока он не станет ненужным

  • Бывает удобно создать объект, который можно использовать после возврата из функции, где он был создан.

Недостатки:

  • Большие накладные расходы

  • Сложность использования

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

1) static int a=0

2) int a=0

#include <stdio.h>

#include <stdlib.h>

int f(){

static int a=0;

a=a+1;

printf("%i \n",a);

}

int main()

{

f();

f();

system("pause");

return 0;

}

#include <stdio.h>

#include <stdlib.h>

int f(){

int a=0;

a=a+1;

printf("%i \n",a);

}

int main()

{

f();

f();

system("pause");

return 0;

}



В первом примере, переменная статическая – память под неё выделяется сразу при загрузке программы и инициализируется нулем, а потом при каждом вызове функции f выделение памяти уже не происходит, поэтому изменяется старое значение статической переменной a. Во втором примере, при каждом заходе в функцию, для автоматической переменной a выделяется память и инициализируется нулем, поэтому пи каждом вызове функции f, мы видим , что она выводит “1”.

Глобальные переменные: Глобальные переменные, в отличие от локальных, доступны в любой точке программы. Но чтобы изменить значение глобальной переменной, необходимо специально объявить её как глобальную. Глобальные переменные хранятся в отдельной фиксированной области памяти, созданной компилятором специально для этого. Глобальные переменные используются в тех случаях, когда разные функции программы используют одни и те же данные. Однако рекомендуется избегать излишнего использования глобальных переменных, потому что они занимают память в течение всего времени выполнения программы, а не только тогда, когда они необходимы. Кроме того, и это еще более важно, использование глобальной переменной делает функцию менее универсальной, потому что в этом случае функция использует нечто, определенное вне ее. К тому же большое количество глобальных переменных легко приводит к ошибкам в программе из-за нежелательных побочных эффектов. При увеличении размера программы серьезной проблемой становится случайное изменение значения переменной где-то в другой части программы, а когда глобальных переменных много, предотвратить это очень трудно. В следующем примере переменная count объявлена вне каких бы то ни было функций. Ее объявление расположено перед main(), однако, оно может находиться в любом месте перед первым использованием этой переменной, но только не внутри функции. Объявлять глобальные переменные рекомендуется в верхней части программы.

#include <stdio.h>

int count; /* глобальная переменная count */

void func1(void);

void func2(void);

int main(void)

{

count = 100;

func1();

return 0;

}

void func1(void)

{

int temp;

temp = count;

func2();

printf("count равно %d", count); /* напечатает 100 */

}

void func2(void)

{

int count;

for(count=1; count<10; count++)

putchar('.');

}

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

Время жизни

Область видимости

Глобальные переменные

От момента запуска до момента окончания программы – на протяжении выполнения всей программы.

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

Статические переменные внутри функций

От момента запуска до момента окончания программы – на протяжении выполнения всей программы.

Видна только внутри функции. Может быть перекрыта одноименными переменными во внутренних блоках {}, например, внутри цикла.

Локальные переменные - автоматические

Существуют от момента объявления до окончания того блока, в котором переменная объявлена.

Блок – это все, что заключено между {}. Функция – то же блок.

Видны внутри блока, в котом объявлены. Могут быть перекрыты одноименными переменными во внутренних блоках.

Стек

Динамически распределяемая область памяти

Глобальные переменные

Код программы

14. Автоматический стековый механизм распределения памяти. Используется ли стековый механизм для глобальных переменных? Стек – это область памяти, в которой хранятся локальные переменные и параметры функций. При вызове функции ее параметры и локальные переменные помещаются в стек. Стек функционирует по принципу стакана – значение, помещенное в стек первым, оказывается на дне стека, в то время как последнее значение – на вершине стека. По завершении работы функции все данные, принадлежащие этой функции, удаляются из стека. Очистка стека начинается с вершины, т. е. со значений, помещенных в стек последними; Скомпилированная программа С имеет четыре логически обособленные области памяти. Первая — это область памяти, содержащая выполнимый код программы. Во второй области хранятся глобальные переменные. Оставшиеся две области — это стек и динамически распределяемая область памяти. Стек используется для хранения вспомогательных переменных во время выполнения программы. Здесь находятся адреса возврата функций, аргументы функций, локальные переменные и т.п. Глобальные переменные хранятся отдельно!!!

15. Стековый механизм распределения памяти. Примеры и траектория вызова функций. Стек – это область памяти, в которой хранятся локальные переменные и параметры функций. При вызове функции ее параметры и локальные переменные помещаются в стек. Стек функционирует по принципу стакана – значение, помещенное в стек первым, оказывается на дне стека, в то время как последнее значение – на вершине стека. По завершении работы функции все данные, принадлежащие этой функции, удаляются из стека. Очистка стека начинается с вершины, т. е. со значений, помещенных в стек последними;

16. Отличие статических переменных от локальных. Статические переменные внутри функций: Время жизни от момента запуска до момента окончания программы-на протяжении выполнения всей программы. Область видимости: видна только внутри функции. Может быть перекрыта одноименными переменными во внутренних блоках {}, например, внутри цикла. Статические переменные объявляются директивой static. Они инициализируются только один раз - при первом вызове функции и сохраняют свое значение даже после выхода из функции. В следующий раз при новом вызове функции статические переменные будут иметь то же значение, которое они имели перед выходом из функции в послений раз.Статические переменные объявляются в пределах описания функции и поэтому доступны для использования только в пределах той функции, в которой они объявлены. Пример объявления статической переменной: int GetOpenPositionsNumber() { static int Count = 0; ... } Локальные переменные – автоматические: Время жизни существуют от момента объявления до окончания того блока, в котором переменная объявлена. Блок – это все, что заключено между {}. Функция – тоже блок. Область видимости: видны внутри блока, в котором объявлены. Могут быть перекрыты одноименными переменами во внутренних блоках. Их значения и даже сам факт, что локальные переменные существуют, известны только данной функции, Другими словами, если вы объявляете локальную переменную с именем salary в функции payroll, то другие функции не имеют доступа к значению переменной salary. Фактически, другие функции не имеют никакого представления о том, что переменная salary существует. При объявлении локальных переменных внутри функции очень вероятно, что имя локальной переменной, объявляемой вами в одной функции, будет таким же , как и имя переменной, используемой в другой функции. Как уже упоминалось, локальные переменные известны только в текущей функции. Таким образом, если две функции используют одно и то же имя для своих локальных переменных, это не приводит к конфликту. Время жизни – это части программы или вся программа, при выполнении которой переменная существует. Область видимости – это часть программы или вся программа, когда возможно получить доступ к объекту.

17. Функции для работы с динамической памятью. Примеры. Динамическое распределение памяти из кучи (heap). Часто бывает удобно создать новый объект, который существует до тех пор, пока он не станет ненужным. В частности, бывает удобно создать объект, который можно использовать после возврата из функции, где он был создан. (определение из лекции) Или Динамическое распределение памяти — способ выделения оперативной памяти компьютера для объектов в программе, при котором выделение памяти под объект осуществляется во время выполнения программы.(используется, если на момент написания программы известен только тип данных, не известен объем выделяемой памяти. В этом случае память должна выделяться в момент исполнения программы). Часто бывает удобно создать новый объект, который существует до тех пор, пока он не станет ненужным. В частности, бывает удобно создать объект, который можно использовать после возврата из функции, где он был создан. Для работой с памятью используются следующие основные функции:

Выделение памяти

Высвобождение памяти

C

Функция:

malloc, calloc

Прототип функции malloc():

void *malloc(size_t кол-во_байт);

t кол-во_байт – тип, описанный в <stdlib.h>, как unsigned int.

Функция:

free

прототип:

void free(void *p)

р — указатель на участок памяти, выделенный перед этим функцией malloc

C++

Функция:New

Функция:delete

Основу системы динамического распределения в С составляют функции malloc() и free(). Функция malloc() выделяет память, а free() — освобождает ее. Это значит, что при каждом запросе функция malloc() выделяет требуемый участок свободной памяти, a free() освобождает его, то есть возвращает системе.

Функции malloc и free описаны в библиотеке <stdlib.h>.

Функция malloc() возвращает указатель типа void *, поэтому его можно присвоить указателю любого типа.

int *p1 = malloc(400);

double *p2= malloc(400);

Выделаются НЕПРЕРЫВНО 400 байт.

Указатели p1 и p2 указывают на начало блока.

По-сути – p1 ссылается на массив из 100 элементов типа int, а p2 – ссылается на 50 элементов типа double.

При успешном выполнении malloc() возвращает указатель на первый байт непрерывного участка памяти, выделенного в динамически распределяемой области памяти.

При необходимости выделения динамической памяти под массив определенного типа и для улучшении переносимости программы на другие платформы нужно использовать sizeof.

int *p;

p = malloc(50*sizeof(int));

Если в динамически распределяемой области памяти недостаточно свободной памяти для выполнения запроса, то память не выделяется и malloc() возвращает нуль (0 или NULL). При каждом размещении данных необходимо проверять, состоялось ли оно.

p = malloc(100);

if(!p) {

printf("Нехватка памяти.\n");

exit(1);

Не использовать указатель р, если он равен нулю!

Функция free() противоположна функции malloc() в том смысле, что она возвращает системе участок памяти, выделенный ранее с помощью функции malloc(). Иными словами, она освобождает участок памяти, который может быть вновь использован функцией malloc().

18. Что такое sizeof. Почему надо использовать sizeof при написании программ. С помощью операции sizeof можно определить размер памяти которая соответствует идентификатору или типу. Операция sizeof имеет следующий формат: sizeof(выражение) . В качестве выражения может быть использован любой идентификатор, либо имя типа, заключенное в скобки. Отметим, что не может быть использовано имя типа void, а идентификатор не может относится к полю битов или быть именем функции. Если в качестве выражения указанно имя массива, то результатом является размер всего массива (т.е. произведение числа элементов на длину типа), а не размер указателя, соответствующего идентификатору массива. Однако убедиться, что вы каждый раз выделяете и освобождаете один и тот же объем памяти, недостаточно. Вы должны обеспечить распределение правильного объема памяти. Надежнее всего использовать в программе функцию SizeOf. Это не только обеспечивает, что вы выделяете и освобождаете один и тот же объем, но гарантирует, что при изменении размера типа ваша программа все равно будет выделять нужную память.

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