Стивен Прата - Язык программирования C. Лекции и упражнения (6-е изд.) 2015
- Название:Язык программирования C. Лекции и упражнения (6-е изд.) 2015
- Автор:
- Жанр:
- Издательство:Вильямс
- Год:0101
- ISBN:нет данных
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Стивен Прата - Язык программирования C. Лекции и упражнения (6-е изд.) 2015 краткое содержание
Язык программирования C. Лекции и упражнения (6-е изд.) 2015 - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
void * memcpy(void * restrict si, const void * restrict s2, size_t n);
void * memmove(void * si, const void * s2, size_t n);
Каждая функция копирует n байтов из местоположения s2 в местоположение si. Функция memcpy() требует, чтобы между местоположениями не было перекрытия, но для функции memmove() такое требование отсутствует. Объявление si и s2 как restrict означает, что каждый указатель является единственным средством доступа, поэтому они не могут обращаться к одному и тому же блоку данных. Это соответствует требованию отсутствия перекрытия. Функция memmove(), которая разрешает перекрытие, при копировании данных должна соблюдать большую осторожность, чтобы не перезаписать данные до того, как они будут использованы.
Ключевое слово restrict имеет две аудитории. Одна из них — компилятор, и restrict сообщает компилятору о том, что он волен делать определенные предположения, касающиеся оптимизации. Другой аудиторией является пользователь, и restrict говорит пользователю о том, что должны применяться только аргументы, удовлетворяющие требованиям restrict. В общем случае компилятор не способен выяснить, соблюдаете ли вы это ограничение, но вы берете на себя риск за его игнорирование.
Квалификатор типа _Atomic (С11)
Параллельное программирование разделяет выполнение программы на потоки, которые могут выполняться параллельно. При этом возникают сложные задачи программирования, в число которых входит управление разными потоками, получающими доступ к одним и тем же данным.
522 глава 12
В СП предоставлены (необязательные) методы управления, организованные в виде необязательных файлов stdatomic.h и threads.h. Одним из аспектов является концепция атомарного типа, для которого доступ управляется разнообразными функциональными макросами. Пока поток выполняет атомарную операцию над объектом атомарного типа, другие потоки не будут иметь доступа к этому объекту. Например, код наподобие
int hogs; // обычное объявление
hogs = 12; // обычное присваивание
можно было бы заменить следующим кодом:
Atomic int hogs; // hogs - атомарная переменная
atomic_store(shogs, 12); // макрос из stdatomic.h
Здесь сохранение значения 12 в hogs представляет собой атомарный процесс, в течение которого другие потоки не будут иметь доступа к hogs.
На время написания этих строк поддержка этой возможности компиляторами только ожидалась.
Новые места для старых ключевых слов
Стандарт С99 позволяет помещать квалификаторы типа и квалификатор класса хранения static в первоначальные квадратные скобки формального параметра в прототипе и заголовке функции. В случае квалификаторов типа это предоставляет альтернативный синтаксис для существующей возможности. Например, вот объявление со старым синтаксисом:
void ofmouthlint * const al, int * restrict a2, int n); // старый стиль
Объявление говорит о том, что al — указатель const на int, и это означает, что константным является сам указатель, но не данные, на которые он указывает. Кроме того, объявление отражает то, что а2 представляет собой указатель restrict, как было описано в предыдущем разделе. Эквивалентный новый синтаксис выглядит следующим образом:
void ofmouth(int al[const], int a2[restrict], int n); //разрешено
// стандартом C99
По существу новое правило разрешает использовать эти два квалификатора либо с формой записи с указателями, либо с формой записи с массивами в объявлении параметров функции.
Случай со static отличается, т.к. он вводит новое и несвязанное применение для этого ключевого слова. Вместо указания области видимости или связывания для переменной со статическим классом хранения новое использование сообщает компилятору, как фор мальный параметр будет применяться. Например, взгляните на следующий прототип:
double sticktdouble ar[static 20]);
Такое использование static отражает то, что фактический аргумент в вызове функции будет указателем на первый элемент массива, имеющего, по меньшей мере, 20 элементов. Цель заключается в том, чтобы позволить компилятору применить эту информацию для оптимизации его кодирования функции. Зачем использовать данное ключевое слово в такой отличающейся манере? Комитет по стандартам С весьма неохотно идет на создание новых ключевых слов, поскольку это может сделать недействительными старые программы, в которых такие слова применялись в качестве идентификаторов, поэтому если удается реализовать новое использование какого-то старого ключевого слова, то так они и поступят.
Классы хранения, связывание и управление памятью 523
Как и restrict, ключевое слово static имеет две аудитории. Одна из них — это компилятор, которому static сообщает, что он имеет возможность делать определенные предположения, касающиеся оптимизации. Другой аудиторией является пользователь, которому static указывает на необходимость предоставлять только такие аргументы, которые удовлетворяют требованиям static.
Ключевые понятия
Язык С предлагает несколько моделей управления памятью. Вы должны ознакомиться со всеми различными вариантами. Вы также должны выработать критерии, когда выбирать тот или иной тип. Большую часть времени наилучщим выбором будет автоматическая переменная. Если вы решите применять другой тип, то для этого должны иметь вескую причину. При взаимодействии между функциями обычно лучше всего использовать автоматические переменные, параметры функций и возвращаемые значения, а не глобальные переменные. С другой стороны, глобальные переменные особенно удобны для представления константных данных.
Вы должны понимать свойства статической памяти, автоматической памяти и выделенной памяти. В частности, имейте в виду, что объем применяемой статической памяти определяется на этапе компиляции, а статические данные загружаются в память при загрузке программы. Память под автоматические переменные выделяется и освобождается во время выполнения, поэтому объем памяти, занимаемой автоматическими переменными, на протяжении выполнения программы меняется. Автоматическую память можно представлять как перезаписываемое рабочее пространство. Выделенная память увеличивается и уменьшается в объеме, но в этом случае процесс управляется вызовами функций, а не происходит автоматически.
Резюме
Память, задействованная под хранение данных в программе, может быть охарактеризована продолжительностью хранения, областью видимости и связыванием. Продолжительность хранения бывает статической, автоматической или выделенной. При статической продолжительности хранения память выделяется в начале выполнения программы и остается занятой на протяжении всего периода выполнения. Если продолжительность хранения является автоматической, то память под переменную выделяется, когда поток управления программы входит в блок, в котором переменная определена, и освобождается, когда управление покидает этот блок. В случае выделенной продолжительности хранения память выделяется вызовом malloc() (или родственной функции) и освобождается вызовом free().
Читать дальшеИнтервал:
Закладка: