на тему рефераты
 
Главная | Карта сайта
на тему рефераты
РАЗДЕЛЫ

на тему рефераты
ПАРТНЕРЫ

на тему рефераты
АЛФАВИТ
... А Б В Г Д Е Ж З И К Л М Н О П Р С Т У Ф Х Ц Ч Ш Щ Э Ю Я

на тему рефераты
ПОИСК
Введите фамилию автора:


Реферат: Лекции по C++


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

     Об"явления переменной на внешнем уровне

               Об"явления переменной на внешнем уровне используют специфи­каторы класса памяти static и extern или совсем опускают их. Спе­цификаторы класса памяти auto и register не допускаются на  внеш­нем уровне.

               Об"явления  переменных  на  внешнем уровне- это определения переменных или ссылки на определения, сделанные в другом месте.

Об"явление внешней переменной, которое  инициализирует  эту

переменную  (явно или неявно), называется определением этой пере­менной. Определение на внешнем уровне может задаваться в  следую­щих различных формах:

               -переменная  на  внешнем уровне может быть определена путем ее об"явления со спецификатором класса памяти static. Такая пере­менная может быть явно инициализирована  константным  выражением. Если  инициализатор отсутствует, то переменная автоматически ини­циализируется нулем во время компиляции. Таким образом,  об"явле­ния  static  int  k = 16; и static int k; оба рассматриваются как определения;

               -переменная определяется, когда она  явно  инициализируется

на  внешнем уровне. Например, int j = 3; это определение перемен­ной.

               Так как переменная определяется на внешнем уровне,  то  она видима  в пределах остатка исходного файла, от места, где она оп­ределена. Переменная не видима выше своего определения в  том  же самом  исходном файле ни в других исходных файлах программы, если не об"явлена ссылка, которая делает ее видимой.

               Переменная может быть определена на внешнем  уровне  внутри исходного файла только один раз. Если задается спецификатор клас­са  памяти static, то в других исходных файлах могут быть опреде­лены переменные с тем  же  именем.  Так  как  каждое  определение static  видимо  только  в  пределах своего собственного исходного файла, то конфликта не возникнет.

               Спецификатор класса памяти extern используется для об"явле­ния ссылки на переменную, определенную где-то в другом месте. Та­кие об"явления используются в случае, когда нужно сделать видимым определение переменной в других исходных файлах или  выше  места, где  она определена в том же самом исходном файле. Так как ссылка на переменную об"явлена на внешнем уровне, то переменная видима в пределах остатка исходного файла от места об"явления ссылки.

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

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

Есть одно исключение из правил, описанных выше. Можно опус-

тить из об"явления  переменной  на  внешнем  уровне  спецификатор класса  памяти и инициализатор. Например, об"явление int n; будет правильным внешним об"явлением. Это об"явление имеет два  различ­ных смысла в зависимости от контекста.

               1.  Если где-нибудь в программе будет определена на внешнем уровне переменная с тем же именем, то об"явление является ссылкой на эту переменную, как если бы был использован спецификатор клас­са памяти extern в об"явлении.

               2.  Если  нет такого определения, то об"явленной переменной распределяется память во время линкования и переменная  инициали­зируется  нулем.  Если  в программе появится более чем одно такое об"явление, то память распределится для  наибольшего  размера  из об"явленных переменных. Например, если программа содержит два не­инициализированных  об"явления переменной i на внешнем уровне int i; и char i; то память во время линкования распределится под  пе­ременную i типа int.

               Неинициализированные об"явления переменной на внешнем уров­не  не  рекомендуются  для файлов, которые могут быть размещены в библиотеку.

               Пример:

                 /*****************************************************

                                                SOURCE FILE ONE *****************************************************/

                 extern int i;                                        /* reference to i

                                                                                                defined below */

                 main()

                 {

                                    i++;

                                    printf("%d\n", i);    /* i equals 4 */

                                    next();

                 }

                 int i = 3;                    /* definition of i */

                 next()

                 {

                                    i++;

                                    printf("%d\n", i);    /* i equals 5 */

                                    other();

                 }

/***************************************************** SOURCE FILE TWO

                 *****************************************************/

                 extern int i;               /* reference to i in

                                                                                                first source file */

                 other()

                 {

                                    i++;

                                    printf("%d\n", i);    /* i equals 6 */

                 }

               Два исходных файла  в  совокупности  содержат  три  внешних об"явления  i. Одно об"явление содержит инициализацию- int i = 3; , где глобальная переменная i определена  с  начальным  значением равным 3.

               Самое  первое  об"явление extern в первом файле делает гло­бальную переменную видимой выше ее определения в файле.

               Без об"явления extern функция main не смогла  бы  сослаться на  глобальную  переменную  i.  Об"явление extern переменной i во втором исходном файле делает глобальную переменную видимой в этом исходном файле.

               Все три функции выполняют одну и ту же задачу: они увеличи­вают i на 1 и печатают  получившееся  значение.  (Предполагается, что функция printf определена где-то еще в программе.). Печатают­ся величины равные 4, 5 и 6.

               Если бы переменная i не была бы инициализирована,она бы бы­ла  автоматически  установлена  в 0 при линковании. В этом случае напечатанные значения были бы равны 1, 2 и 3.

Об"явление переменной на внутреннем уровне

               Любой из четырех спецификаторов класса  памяти  может  быть использован  для об"явления переменной на внутреннем уровне. Если спецификатор класса памяти опускается в об"явлении переменной  на внутреннем уровне, то подразумевается класс памяти auto.

Спецификатор  класса памяти auto об"являет переменную с ло-

кальным временем жизни. Переменная видима только в том блоке, где она об"явлена. Об"явления переменных auto могут включать  инициа­лизаторы.  Переменные класса памяти auto автоматически не инициа­лизируются, а инициализируются явно при об"явлении или присваива­нии начальных значений, посредством операторов внутри блока. Если нет инициализации, то величина переменной auto считается  неопре­деленной.

               Спецификатор  класса памяти register сообщает компилятору о том, чтобы он распределил память под переменную в регистре,  если это  возможно. Использование регистровой памяти обычно приводит к более быстрому времени доступа и к меньшему размеру  результирую­щего кода. Переменные, об"явленные с классом памяти register име-

ют ту же самую видимость, что и переменные auto.

               Число регистров, которое может быть использовано под память переменных,  зависит от машины. Когда компилятор встречает специ­фикатор класса памяти register в об"явлении, а свободного регист­ра не имеется, то для  переменной  распределяется  память  класса auto.  Компилятор  назначает  переменным регистровую память в том порядке, в котором появляются об"явления в исходном файле. Регис­тровая память, если она имеется, гарантирована только для  целого и адресного типов.

               Переменная,  об"явленная на внутреннем уровне со специфика­тором класса памяти static,имеет глобальное время жизни  и  имеет видимость только внутри блока, в котором она об"явлена. В отличие от переменных auto, переменные, об"явленные как static, сохраняют свое значение при завершении блока.

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

               Переменная,  об"явленная  со  спецификатором  класса памяти extern, является ссылкой на переменную с тем же самым именем, оп­ределенную на внешнем уровне в любом исходном файле программы.

Цель внутреннего об"явления extern  состоит  в  том,  чтобы

сделать  определение  переменной  внешнего  уровня видимой внутри блока. Внутреннее об'явление extern не  изменяет  видимость  гло­бальной переменной в любой другой части программы.

               Пример:

               int i = 1;

               main()

                 {                 /* reference to i, defined above */

                                    extern int i;

/* initial value is zero; a is

visible only within main */

                                    static int a;

/* b is stored in a register, if possible */ register int b = 0;

/* default storage class is auto */

                                    int c = 0;

/* values printed are 1, 0, 0, 0 */ printf("%d\n%d\n%d\n%d\n", i, a, b, c);

                                    other();

                 }

                 other()

                 {

                                    /* i is redefined */

                                    int i = 16;

                                    /* this a is visible only within other */

                                    static int a = 2;

                                    a += 2;

/* values printed are 16, 4 */

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

                 }

               Переменная i определяется на внешнем уровне с инициализаци­ей  1.  В  функции  main  об"явлена ссылка extern на переменную i внешнего уровня. Переменная класса  памяти  static  автоматически

устанавливается  в 0, так как инициализатор опущен. Вызов функции print (предполагается, что функция print  определена  в  каком-то месте исходной программы.) печатает величины 1, 0, 0, 0.

               В  функции other, переменная i переопределяется как локаль­ная переменная с начальным значением 16. Это не влияет на  значе­ние внешней переменной i. Переменная a об"является как переменная класса памяти static с начальным значением 2. Она не противоречит переменной a, об"явленной в функции main, так как видимость пере­менных  класса памяти static на внутреннем уровне ограничена бло­ком, в котором она об"явлена.

               Значение переменной увеличивается на 2 и становится  равным 4.  Если бы функция other была вызвана снова в той же самой прог­рамме, то начальное значение a стало бы равным 4. Внутренние  пе­ременные  класса памяти static сохраняют свои значения, когда за­канчивается выполнение блока, в котором они об"явлены.

     Об"явление функции на внешнем и внутреннем уровнях

               Функции могут быть об"явлены со спецификаторами класса  па­мяти  static  или  extern.  Функции всегда имеют глобальное время жизни.

               Правила видимости для функций отличаются от правил видимос­ти для переменных. Об"явления функций на внутреннем уровне  имеют тот  же самый смысл, что и об"явления на внешнем уровне. Это зна­чит, что функции не могут иметь  блочной  видимости  и  видимость функций  не может быть вложенной. Функция об"явленная как static,

видима только в пределах исходного файла, в котором она определя­ется. Любая функция в том же самом исходном файле  может  вызвать функцию  static,  но функции static из других файлов нет. Функция static с тем же самым именем может быть об"явлена в другом исход­ном файле.

               Функции, об"явленные как extern видимы в пределах всех  ис­ходных  файлов, которые составляют программу. Любая функция может вызвать функцию extern.

               Об"явления функций, в которых  опущен  спецификатор  класса памяти, считаются по умолчанию extern.

     Инициализация

               В об"явлении переменной может быть присвоено начальное зна­чение посредством инициализатора. Величина или величины инициали­затора присваиваются переменной.

               Синтаксически, записи инициализатора предшествует знак рав­но (=)

                 =<initializer>

               Могут быть инициализированы переменные любого типа. Функции не  инициализируются. Об"явления, которые используют спецификатор класса памяти extern не могут содержать инициализатора.

Переменные, об"явленные на внешнем уровне, могут быть  ини-

циализированы. Если они явно не инициализированы, то они устанав­ливаются  в  нуль во время компиляции или линкования. Любая пере­менная, об"явленная со спецификатором класса памяти static, может быть инициализирована константным выражением. Инициализация пере­менных класса static выполняется один раз  во  время  компиляции. Если отсутствует явная инициализация, то переменные класса памяти static автоматически устанавливаются в нуль.

               Инициализация переменных auto и register выполняется каждый раз при входе в блок, в котором они об"явлены. Если инициализатор опущен  в  об"явлении переменной класса памяти auto или register, то начальное значение  переменной  не  определено.  Инициализация

составных  типов  auto (массив, структура, совмещение) запрещена. Любое составное об"явление класса памяти static может быть иници­ализировано на внешнем уровне.

               Начальными значениями для внешних об"явлений  переменной  и для  всех  переменных  static как внешних так и внутренних должно быть константное выражение. Автоматические и регистровые перемен­ные могут быть инициализированы константными или переменными  ве­личинами.

Базовые типы и типы указателей

               Синтаксис:

               =<expression>

               Величина  выражения присваивается переменной. Для выражения допустимы правила преобразования.

               Примеры:

                 int x = 10;                    /* Example 1 */

register int *px = 0;          /* Example 2 */ int c = (3 * 1024);            /* Example 3 */ int *b = &x;                   /* Example 4 */

               В первом примере x инициализируется константным  выражением 10.  Во втором примере, указатель px инициализирован нулем, в ре­зультате чего получился "null" указатель. В третьем  примере  ис­пользуется константное выражение для инициализации c. В четвертом примере инициализируется указатель b адресом другой переменной x.

     Составные типы

               Синтаксис:

               ={<initializer-list>}

               Список  инициализаторов <initializer-list> - это последова­тельность инициализаторов, разделенных запятыми. Каждый инициали­затор в последовательности- это либо константное выражение,  либо список  инициализаторов.  Поэтому,  заключенный в фигурные скобки список, может появиться внутри другого списка инициализации.  Эта конструкция  используется  для  инициализации элементов составных конструкций.

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

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

               Эти правила применяются к каждому вложенному списку инициа­лизаторов, точно так же как и ко всей конструкции в целом.

               Пример:

               int p[4] [3] = {

                                       { 1, 1, 1 },

{ 2, 2, 2 }, { 3, 3, 3,}, { 4, 4, 4,},

                 };

               В  примере  об"является  массив p размерности 4 строки на 3 столбца. Элементы первой строки инициализируются 1, второй строки

2 и т. д. Заметим, что списки инициализаторов третьей и четвертой строк заканчиваются запятой. Последний список  инициализаторов  { 4, 4, 4,} также заканчивается запятой.

               Эти  дополнительные  запятые  допускаются, но не требуются. Требуются только те запятые, которые разделяют константные  выра­жения  и  списки  инициализации.  Если  список инициализаторов не структурирован под составной об"ект, то его величины присваивают­ся в том порядке, в котором подстыкованы элементы об"екта. Поэто­му вышеприведенная инициализация эквивалентна следующей:

               int p[4] [3] = {

1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4

                 };

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

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

               typedef struct {

                           int n1, n2, n3;

                 } triplet;

                 triplet nlist[2] [3] = {

{ { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } },  /* Line 1 */ { { 10,11,12}, { 13,14,15}, { 15,16,17} }   /* Line 2 */

                 };

               В  примере nlist об"является как массив структур, состоящий из двух строк и трех столбцов. Каждая структура состоит  из  трех элементов.  Первая строка инициализации назначает величины первой строке массива nlist следующим образом:

               1. Первая левая фигурная скобка Line 1 информирует компиля­тор о том, что это начало  инициализации  первой  строки  массива nlist(nlist[0]).

               2. Вторая левая фигурная скобка означает то, что начинается инициализация  первого  элемента первой строки массива ( nlist[0] [0] ).

               3. Первая правая фигурная скобка сообщает об окончании ини­циализации первого элемента- структуры  nlist[0]  [0].  Следующая левая  фигурная  скобка  сообщает  о начале инициализации второго элемента первой строки nlist[0] [1].

               4. Процесс продолжается до конца Line 1 и заканчивается  по последней правой фигурной скобке.

               Аналогично, Line 2 назначает величины второй строке массива nlist.

               Заметим, что внешние фигурные скобки инициализаторов Line 1 и  Line 2 требуются. Следующая конструкция, в которой внешние фи­гурные скобки опущены будет неверной.

/* THIS CAUSES AN ERROR */

                 triplet nlist[2] [3] = {

                   { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 },  /* Line 1 */

                   { 10,11,12}, { 13,14,15}, {16,17,18 }   /* Line 2 */

               };

               В этом примере первая левая фигурная скобка в Line 1  стар­тует  инициализацию  nlist[0],  которая является массивом из трех структур. Величины 1, 2,  3  назначаются  трем  элементам  первой структуры. Когда встретится правая фигурная скобка (после величи­ны  3), инициализация nlist[0] закончится и две оставшиеся струк­туры автоматически инициализируются нулем. Аналогично, { 4, 5,  6 }  инициализирует  первую структуру во второй строке nlist, а ос­тавшиеся две структуры nlist[1] установятся в нуль. Когда  компи­лятор встретит следующий список инициализации { 7, 8, 9 }, то это приведет  к  попытке инициализировать nlist[2]. Так как nlist со­держит только две строки, то будет выдано сообщение об ошибке.

               Примеры:

/******************* Example 1 *********************/

                 struct list {

                                    int i, j, k;

                                     float n[2] [3];

                                    } x = {

                                                     1,

                                                     2,

                                                     3,

{4.0, 4.0, 4.0}

                                  };

/******************* Example 2 *********************/

                 union {

                                  char x[2] [3];

                                  int i, j, k;

                                  } y = {

                                                     {'1'},

                                                     {'4'}

                                  };

               В первом примере три элемента int структурной переменной  x инициализированы  1,  2,  и 3 соответственно. Три элемента первой строки массива m инициализированы как 4.0. Элементы второй строки инициализированы нулем по умолчанию.

               Во втором примере инициализируется переменная y типа совме­щения. Первым элементом совмещения является массив, для  которого требуется составной инициализатор. Список инициализации {'1'} за­дает величины для первой строки массива. Поскольку в списке всего одна  величина, то только первый элемент строки массива инициали­зируется символом 1 , а оставшиеся два элемента в строке  инициа­лизируются  нулем  (символом  \0)  по умолчанию. Аналогично, первый элемент второй строки массива x инициализируется  символом  4,  а оставшиеся два элемента в строке инициализируются нулем.

     Строковые инициализаторы

Массив может быть инициализирован строчным литералом.

               Например,

                 char code[ ] = "abc";

               инициализирует  code как массив символов из четырех элемен­тов. Четвертым элементом является символ \0, который завершает  все строковые литералы.

               Если  специфицируется  размер  массива, а строка больше чем

специфицированный размер, то лишние символы отбрасываются. Следу­ющее об"явление инициализирует переменную code, как  трехэлемент­ный массив символов:

               char code[3] = "abcd"

               В примере только три первые символа инициализатора назнача­ются для массива code. Символ d и сивол нуль отбрасываются.

               Если  строка  короче, чем специфицированный размер массива, то оставшиеся элементы массива инициализируются  нулем  (символом \0).

     Об"явления типов

               Об"явление  типа определяет имя и элементы структурного или совмещающего типов или имя и перечислимое множество перечислимого типа.

Страницы: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11


на тему рефераты
НОВОСТИ на тему рефераты
на тему рефераты
ВХОД на тему рефераты
Логин:
Пароль:
регистрация
забыли пароль?

на тему рефераты    
на тему рефераты
ТЕГИ на тему рефераты

Рефераты бесплатно, реферат бесплатно, курсовые работы, реферат, доклады, рефераты, рефераты скачать, рефераты на тему, сочинения, курсовые, дипломы, научные работы и многое другое.


Copyright © 2012 г.
При использовании материалов - ссылка на сайт обязательна.