Сделай Сам Свою Работу на 5

R.3.3 Программа и связывание





 

Программа состоит из одного или нескольких файлов, связываемых вместе (§R.2). Файл состоит из последовательности описаний.

Имя с файловой областью видимости, которое явно описано как static, является локальным в своей единице трансляции и может использоваться для именования объектов, функций и т.п. в других единицах трансляции. Говорят, что такие имена имеют внутреннее связывание. Имя с файловой областью видимости, которое явно описано со спецификацией inline, является локальным в своей единице трансляции. Имя с файловой областью видимости, которое явно описано со спецификацией const и не описано явно как extern, считается локальным в своей единице трансляции. То же верно для имени класса, которое не использовалось в нелокальных для данной единицы трансляции описаниях объекта, функции или класса, и который не имеет статических членов (§R.9.4), не имеет функций-членов, кроме подстановок (§R.9.3.2). Всякое описание некоторого имени с файловой областью видимости, которое не описано одним из перечисленных способов так, чтобы иметь внутреннее связывание, в многофайловой программе обозначает один и тот же объект (§R.3.7), функцию (§R.8.2.5) или класс (§R.9). Такие имена называются внешними или говорят, что они имеют внешнее связывание. В частности, поскольку нельзя описать имя класса как static, всякое употребление имени некоторого класса с файловой областью видимости, который (класс) использовался для описания объекта или функции с внешним связыванием, или же который имеет статический член или функцию-член, не являющуюся подстановкой, будет обозначать один и тот же класс.



Имена определяемых типов (typedef §R.7.13), элементы перечисления (§R.7.2) или имена шаблонов типа (§R.14) не имеют внешнего связывания.

Статические члены класса (§R.9.4) допускают внешнее связывание.

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

Локальные имена (§R.3.2), явно описанные со спецификацией extern, имеют внешнее связывание, если только они уже не были описаны как static (§R.7.1.1).

Типы, используемые во всех описаниях некоторого внешнего имени, должны совпадать, за исключением использования имен определяемых типов (§R.7.1.3) и указания границ массивов (§R.8.2.4). Должно быть в точности одно определение для каждой функции, объекта, класса и элемента перечисления, используемых в программе. Однако, если функция никогда не вызывается и ее адрес никогда не используется, ее не нужно определять. Аналогично, если имя класса используется только таким образом, что не требуется знать определение класса, то класс не нужно определять.



Область видимости функции может быть только файл или класс.

С помощью спецификации связывания можно добиться связывания с описаниями на другом языке (§R.7.4).

 

R.3.4 Начало и окончание программы

 

Программа должна содержать функцию с именем main(). Ей приписывается роль начала программы. Эта функция не является предопределенной для транслятора, она не может быть перегружена, а ее тип зависит от реализации. Предполагается, что любая реализация должна допускать два приведенных ниже определения и что можно добавлять после argv любые параметры. Функция main может определяться так

int main() {/*… */}

или

int main(int argc, char* argv[]) {/*… */}

В последнем определении argc задает число параметров, передаваемых программе окружением, в котором она выполняется. Если argc не равно нулю, параметры должны передаваться как строки, завершающиеся символом '\0', с помощью argv[0] до argv[argc-1], причем argv[0] должно быть именем, под которым программа была запущена, или "". Должно гарантироваться, что argv[argc]==0.

Функция main() не должна вызываться в программе. Связывание main() (§R.3.3) зависит от реализации. Нельзя получать адрес main() и не следует описывать ее как inline или static.



Вызов функции

void exit(int);

описанной в ‹stdlib.h›, завершает программу. Значение параметра передается окружению программы в качестве результата программы.

Инициализация нелокальных статических объектов (§R.3.5) единицы трансляции происходит прежде первого обращения к функции или объекту, определенному в этой единице трансляции. Эта инициализация (§R.8.4, §R.9.4, §R.12.1, §R.12.6.1) может быть проведена перед выполнением первого оператора main() или отложена до любого момента, предшествующего первому использованию функции или объекта, определенных в данной единице трансляции. Все статические объекты по умолчанию инициализируются нулем (§R.8.4) прежде любой динамической (во времени выполнения программы) инициализации. Больше никаких требований на порядок инициализации объектов из различных единиц трансляции не налагается. Инициализация локальных и статических объектов описана в §R.8.4.

Деструкторы (§R.12.4) для инициализированных статических объектов вызываются при возврате из main() или при вызове exit().

Уничтожение происходит в обратном порядке по сравнению с инициализацией. С помощью функции atexit() из ‹stdlib.h› можно указать функцию, которую нужно вызывать при выходе из программы. Если было обращение к функции atexit(), объекты, инициализированные до вызова atexit(), не должны уничтожаться до тех пор, пока не произойдет вызов функции, указанной в atexit(). Если реализация C++ сосуществует с реализацией С, все действия, которые должны были произойти после вызова функции, заданной в atexit(), происходят только после вызова всех деструкторов.

Вызов функции

void abort();

описанной в ‹stdlib.h›, завершает программу без выполнения деструкторов статических объектов и без вызова функций, заданных в atexit().

 

R.3.5 Классы памяти

 

Существует два описываемых класса памяти: автоматический и статический.

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

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

Автоматические объекты инициализируются (§R.12.1) всякий раз, когда управление переходит в блок, где они определены и уничтожаются (§R.12.4) по выходе из этого блока (§R.6.7).

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

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

Статические объекты инициализируются и уничтожаются в соответствии с описанием в §R.3.4 и §R.6.7. С некоторыми объектами не связано никакого имени, см. §R.5.3.3 и §R.12.2. Все глобальные объекты имеют класс памяти статический. Локальным объектам и членам класса можно предать класс памяти статический с помощью явного использования спецификации класса памяти static (§R.7.1.1).

 

R.3.6 Типы

 

Существуют два вида типов: основные и производные.

 

R.3.6.1 Основные типы

 

Существует несколько основных типов. В стандартном заголовочном файле ‹limits.h› задаются в зависимости от реализации минимальные и максимальные значения каждого типа.

Объекты, описанные как символы (char), могут хранить любой элемент из базового набора символов данной машины. Если символ этого набора хранится в символьной переменной, то ее значение равно целому значению кода этого символа. Символы могут явно описываться как unsigned или signed. Обычный char, signed char и unsigned char являются тремя различными типами. Для всех этих трех типов требуется одинаковый объем памяти.

С помощью описаний short int, int и long int можно определить целые трех различных размеров. Для длинных целых требуется памяти не меньше чем для коротких целых, но в реализации или короткие целые, или длинные целые, или и те и другие могут оказаться эквивалентными обычным целым. Обычные целые имеют размер, определяемый системой команд, размеры других целых определяются конкретными потребностями.

Для каждого из типов signed char, short, int и long существует соответствующий беззнаковый тип, который занимает тот же объем памяти и удовлетворяет тем же требованиям выравнивания. Требование выравнивание - это ограничение на значение указателя на данный объект, которое накладывает реализация (§R.5.4).

Беззнаковые целые, описанные как unsigned, подчиняются законом арифметики по модулю 2n, где n число битов, используемое для представления значения. Отсюда следует, что в арифметике беззнаковых не возникает переполнения.

Существует три типа с плавающей точкой: float, double и long double. Тип double гарантирует не меньшую точность представления, чем float, а тип long double гарантирует точность не меньше, чем у double. Характеристики основных типов с плавающей точкой определяются в соответствии с реализацией в стандартном заголовочном файле ‹float.h›.

Типы char, int любых размеров и тип перечисления (§R.7.2) называются целочисленными типами. Целочисленные типы вместе с типами с плавающей точкой образуют арифметические типы.

Тип void задает пустое множество значений. Он используется для обозначения типа функций, которые не возвращают результат. Нельзя описывать объекты с типом void. Любое выражение можно явно преобразовать к типу void (§R.5.4), получившееся выражение можно использовать только как выражение-оператор (§R.6.2), как левый операнд операции запятая (§R.5.18) или в качестве второго или третьего операнда в операции ?: (§R.5.16).

 

R.3.6.2 Производные типы

 

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

массив объектов данного типа, §R.8.4;

функции, имеющие параметры данного типа и возвращающие объекты данного типа, §R.8.2.5;

указатели на объекты или функции данного типа, §R.8.2.1;

ссылки на объекты или функции данного типа, §R.8.2.2;

константы, являющиеся значениями данного типа, §R.7.1.6;

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

структуры, которые являются классами без стандартных ограничений на доступ, $$r.11;

объединения, которые являются структурами, способными содержать в разное время объекты различных типов, §R.9.5;

указатели на члены классов, которые задают члены данного типа среди всех объектов данного класса, §R.8.2.3.

В общем случае указанные методы построения объектов могут применяться рекурсивно, ограничения приведены в $$r.8.2.1, §R.8.2.4, §R.8.2.5 и §R.8.2.2.

Про указатель на объекты типа T говорят "указатель на на T". Например, про указатель на объект типа int говорят "указатель на int", а указатель на объект класса X называется "указатель на X".

Объекты типа void* (указатель на void), const void* и volatile void* могут использоваться как указатели на объекты неизвестного типа. Объект типа void* должен иметь достаточно памяти, чтобы хранить указатель на любой объект.

Все фрагменты руководства, говорящие об "указателях", не относятся к указателям на члены, за исключением указателей на статические члены.

 

R.3.6.3 Имена типов

 

Основные и производные типы можно поименовать с помощью механизма typedef (§R.7.1.3), а семейство типов и функций можно задать и поименовать с помощью механизма шаблона типов (§R.14).

 

 

R.3.7 Адреса

 

Любой объект - это некоторая область памяти, адрес - выражение, ссылающееся на объект или функцию. Очевидным примером адреса будет имя объекта. Существуют операции, порождающие адреса, например, если E выражение типа указатель, то *E - адресное выражение, соответствующее объекту, на который указывает E. Термин "адрес" ("lvalue" т.е. left value - левая величина) появляется из оператора присваивания E1 = E2, где левый операнд E1 должен "адресовать" изменяемую переменную. При обсуждении всех операций в §R.5 указывается применимы ли они к адресным операндам и порождают ли они сами адреса. Адрес может изменяться, если он не является именем функции, именем массива или const.

 

 

 








Не нашли, что искали? Воспользуйтесь поиском по сайту:



©2015 - 2024 stydopedia.ru Все материалы защищены законодательством РФ.