ТОП 10:

Область действия: внешние переменные



Переменные в MAIN(LINE, SAVE и т.д.) являются внутренни-ми или локальными по отношению к функции MAIN, потому чтоони описаны внутри MAIN и никакая другая функция не имеет кним прямого доступа. Это же верно и относительно переменныхв других функциях; например, переменная I в функции GETLINEникак не связана с I в COPY. Каждая локальная переменная су-ществует только тогда, когда произошло обращение к соответс-твующей функции, и исчезает, как только закончится выполне-ние этой функции. По этой причине такие переменные, следуятерминологии других языков, обычно называют автоматическими.Мы впредь будем использовать термин автоматические при ссыл-ке на эти динамические локальные переменные. /в главе 4 об-суждается класс статической памяти, когда локальные перемен-ные все же оказываются в состоянии сохранить свои значениямежду обращениями к функциям/. Поскольку автоматические переменные появляются и исчеза-ют вместе с обращением к функции, они не сохраняют своихзначений в промежутке от одного вызова до другого, в силучего им при каждом входе нужно явно присваивать значения.Если этого не сделать, то они будут содержать мусор. В качестве альтернативы к автоматическим переменным мож-но определить переменные, которые будут внешними для всехфункций, т.е. Глобальными переменными, к которым может обра-титься по имени любая функция, которая пожелает это сделать.(этот механизм весьма сходен с "COMMON" в фортране и"EXTERNAL" в PL/1). Так как внешние переменные доступны всю-ду, их можно использовать вместо списка аргументов для пере-дачи данных между функциями. Кроме того, поскольку внешниепеременные существуют постоянно, а не появляются и исчезаютвместе с вызываемыми функциями, они сохраняют свои значенияи после того, как функции, присвоившие им эти значения, за-вершат свою работу. Внешняя переменная должна быть определена вне всех функ-ций; при этом ей выделяется фактическое место в памяти. Та-кая переменная должна быть также описана в каждой функции,которая собирается ее использовать; это можно сделать либоявным описанием EXTERN, либо неявным по контексту. Чтобысделать обсуждение более конкретным, давайте перепишем прог-рамму поиска самой длинной строки, сделав LINE, SAVE и MAXвнешними переменными. Это потребует изменения описаний и телвсех трех функций, а также обращений к ним. #DEFINE MAXLINE 1000 /* MAX. INPUT LINE SIZE*/ CHAR LINE[MAXLINE]; /* INPUT LINE */CHAR SAVE[MAXLINE];/* LONGEST LINE SAVED HERE*/INT MAX;/*LENGTH OF LONGEST LINE SEEN SO FAR*/MAIN() /*FIND LONGEST LINE; SPECIALIZED VERSION*/{ INT LEN; EXTERN INT MAX; EXTERN CHAR SAVE[]; MAX = 0; WHILE ( (LEN = GETLINE()) > 0 ) IF ( LEN > MAX ) { MAX = LEN; COPY(); }IF ( MAX > 0 ) /* THERE WAS A LINE */ PRINTF( "%S", SAVE );} GETLINE() /* SPECIALIZED VERSION */{ INT C, I; EXTERN CHAR LINE[]; FOR (I = 0; I < MAXLINE-1 && (C=GETCHAR()) !=EOF && C!='\N'; ++I) LINE[I] = C; ++I; } LINE[I] = '\0' RETURN(I) } COPY() /* SPECIALIZED VERSION */ { INT I; EXTERN CHAR LINE[], SAVE[]; I = 0; WHILE ((SAVE[I] = LINE[I]) !='\0') ++I; } Внешние переменные для функций MAIN, GETLINE и COPY оп-ределены в первых строчках приведенного выше примера, кото-рыми указывается их тип и вызывается отведение для них памя-ти. синтаксически внешние описания точно такие же, как опи-сания, которые мы использовали ранее, но так как они распо-ложены вне функций, соответствующие переменные являютсявнешними. Чтобы функция могла использовать внешнюю переме-ную, ей надо сообщить ее имя. Один способ сделать это -включить в функцию описание EXTERN; это описание отличаетсяот предыдущих только добавлением ключевого слова EXTERN. В определенных ситуациях описание EXTERN может быть опу-щено: если внешнее определение переменной находится в том жеисходном файле, раньше ее использования в некоторой конкрет-ной функции, то не обязательно включать описание EXTERN дляэтой переменной в саму функцию. Описания EXTERN в функцияхMAIN, GETLINE и COPY являются, таким образом, излишними.Фактически, обычная практика заключается в помещении опреде-лений всех внешних переменных в начале исходного файла ипоследующем опускании всех описаний EXTERN. Если программа находится в нескольких исходных файлах, инекоторая переменная определена, скажем в файле 1, а исполь-зуется в файле 2, то чтобы связать эти два вхождения пере-менной, необходимо в файле 2 использовать описание EXTERN.Этот вопрос подробно обсуждается в главе 4. Вы должно быть заметили, что мы в этом разделе при ссыл-ке на внешние переменные очень аккуратно используем словаописание и определение. "Определение" относится к тому мес-ту, где переменная фактически заводится и ей выделяется па-мять; "описание" относится к тем местам, где указываетсяприрода переменной, но никакой памяти не отводится. Между прочим, существует тенденция объявлять все, что нипопадется, внешними переменными, поскольку кажется, что этоупрощает связи, - списки аргументов становятся короче и пе-ременные всегда присутствуют, когда бы вам они ни понадоби-лись. Но внешние переменные присутствуют и тогда, когда вы вних не нуждаетесь. Такой стиль программирования чреват опас-ностью, так как он приводит к программам, связи данных внут-ри которых не вполне очевидны. Переменные при этом могут из-меняться неожиданным и даже неумышленным образом, а програм-мы становится трудно модифицировать, когда возникает такаянеобходимость. Вторая версия программы поиска самой длиннойстроки уступает первой отчасти по этим причинам, а отчастипотому, что она лишила универсальности две весьма полезныефункции, введя в них имена переменных, с которыми они будутманипулировать. Упражнение 1-18 --------------- Проверка в операторе FOR функции GETLINE довольно неук-люжа. Перепишите программу таким образом, чтобы сделать этупроверку более ясной, но сохраните при этом то же самое по-ведение в конце файла и при переполнении буфера. Является лиэто поведение самым разумным?

Резюме

На данном этапе мы обсудили то, что можно бы назватьтрадиционным ядром языка "C". Имея эту горсть строительныхблоков, можно писать полезные программы весьма значительногоразмера, и было бы вероятно неплохой идеей, если бы вы за-держались здесь на какое-то время и поступили таким образом:следующие ниже упражнения предлагают вам ряд программ нес-колько большей сложности, чем те, которые были приведены вэтой главе. После того как вы овладеете этой частью "C", приступайтек чтению следующих нескольких глав. Усилия, которые вы приэтом затратите, полностью окупятся, потому что в этих главахобсуждаются именно те стороны "C", где мощь и выразитель-ность языка начинает становиться очевидной. Упражнение 1-19 --------------- Напишите программу DETAB, которая заменяет табуляции вовводе на нужное число пробелов так, чтобы промежуток дости-гал следующей табуляционной остановки. Предположите фиксиро-ванный набор табуляционных остановок, например, через каждыеN позиций. Упражнение 1-20 ---------------- Напишите программу ENTAB, которая заменяет строки пробе-лов минимальным числом табуляций и пробелов, достигая приэтом тех же самых промежутков. Используйте те же табуляцион-ные остановки, как и в DETAB. Упражнение 1-21 ---------------- Напишите программу для "сгибания" длинных вводимых строкпосле последнего отличного от пробела символа, стоящего достолбца N ввода, где N - параметр. убедитесь, что ваша прог-рамма делает что-то разумное с очень длинными строками и вслучае, когда перед указанным столбцом нет ни табуляций, нипробелов. Упражнение 1-22 ---------------- Напишите программу удаления из "C"-программы всех ком-ментариев. Не забывайте аккуратно обращаться с "закавыченны-ми" строками и символьными константами. Упражнение 1-23 ---------------- Напишите программу проверки "C"-программы на элементар-ные синтаксические ошибки, такие как несоответствие круглых,квадратных и фигурных скобок. Не забудьте о кавычках, какодиночных, так и двойных, и о комментариях. (Эта программавесьма сложна, если вы будете писать ее для самого общегослучая).

* 2. Типы, операции и выражения *

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

Имена переменных

Хотя мы этого сразу прямо не сказали, существуют некото-рые ограничения на имена переменных и символических конс-тант. Имена составляются из букв и цифр; первый символ дол-жен быть буквой. Подчеркивание "_" тоже считается буквой;это полезно для удобочитаемости длинных имен переменных.Прописные и строчные буквы различаются; традиционная практи-ка в "с" - использовать строчные буквы для имен переменных,а прописные - для символических констант. Играют роль только первые восемь символов внутреннегоимени, хотя использовать можно и больше. Для внешних имен,таких как имена функций и внешних переменных, это число мо-жет оказаться меньше восьми, так как внешние имена использу-ются различными ассемблерами и загрузчиками. Детали приво-дятся в приложении а. Кроме того, такие ключевые слова какIF, ELSE, INT, FLOAT и т.д., зарезервированы: вы не можетеиспользовать их в качестве имен переменных. (Они пишутсястрочными буквами). Конечно, разумно выбирать имена переменных таким обра-зом, чтобы они означали нечто, относящееся к назначению пе-ременных, и чтобы было менее вероятно спутать их при написа-нии.

Типы и размеры данных

Языке "C" имеется только несколько основных типов дан-ных:CHAR один байт, в котором может находиться один символ извнутреннего набора символов.INT Целое, обычно соответствующее естественному размеру це-лых в используемой машине.FLOAT С плавающей точкой одинарной точности.DOUBLE С плавающей точкой двойной точности. Кроме того имеется ряд квалификаторов, которые можно ис-пользовать с типом INT: SHORT (короткое), LONG (длинное) иUNSIGNED (без знака). Квалификаторы SHORT и LONG указываютна различные размеры целых. Числа без знака подчиняются за-конам арифметики по модулю 2 в степени N, где N - число би-тов в INT; числа без знаков всегда положительны. Описания сквалификаторами имеют вид: SHORT INT X; LONG INT Y; UNSIGNED INT Z; Cлово INT в таких ситуациях может быть опущено, чтообычно и делается. Количество битов, отводимых под эти объекты зависит отимеющейся машины; в таблице ниже приведены некоторые харак-терные значения. Таблица 1 --------------------------------------------------------- ! DEC PDP-11 HONEYWELL IBM 370 INTERDATA ! 6000 8/32 ! ! ASCII ASCII EBCDIC ASCII ! ! CHAR 8-BITS 9-BITS 8-BITS 8-BITS ! INT 16 36 32 32 ! SHORT 16 36 16 16 ! LONG 32 36 32 32 ! FLOAT 32 36 32 32 ! DOUBLE 64 72 64 64 ! ! --------------------------------------------------------- Цель состоит в том, чтобы SHORT и LONG давали возмож-ность в зависимости от практических нужд использовать раз-личные длины целых; тип INT отражает наиболее "естественный"размер конкретной машины. Как вы видите, каждый компиляторсвободно интерпретирует SHORT и LONG в соответствии со свои-ми аппаратными средствами. Все, на что вы можете твердо по-лагаться, это то, что SHORT не длиннее, чем LONG.

Константы

Константы типа INT и FLOAT мы уже рассмотрели. Отметимеще только, что как обычная 123.456е-7, так и "научная" запись 0.12е3 для FLOAT является законной. Каждая константа с плавающей точкой считается имеющейтип DOUBLE, так что обозначение "E" служит как для FLOAT,так и для DOUBLE. Длинные константы записываются в виде 123L. Обычная це-лая константа, которая слишком длинна для типа INT, рассмат-ривается как LONG. Существует система обозначений для восьмеричных и шест-надцатеричных констант: лидирующий 0(нуль) в константе типаINT указывает на восьмеричную константу, а стоящие впереди0X соответствуют шестнадцатеричной константе. Например, де-сятичное число 31 можно записать как 037 в восьмеричной фор-ме и как 0X1F в шестнадцатеричной. Шестнадцатеричные и вось-меричные константы могут также заканчиваться буквой L, чтоделает их относящимися к типу LONG.

Символьная константа

Символьная константа - это один символ, заключенный водинарные кавычки, как, например, 'х'. Значением символьнойконстанты является численное значение этого символа во внут-реннем машинном наборе символов. Например, в наборе символовASCII символьный нуль, или '0', имеет значение 48, а в кодеEBCDIC - 240, и оба эти значения совершенно отличны от числа0. Написание '0' вместо численного значения, такого как 48или 240, делает программу не зависящей от конкретного чис-ленного представления этого символа в данной машине. Сим-вольные константы точно так же участвуют в численных опера-циях, как и любые другие числа, хотя наиболее часто они ис-пользуются в сравнении с другими символами. Правила преобра-зования будут изложены позднее. Некоторые неграфические символы могут быть представленыкак символьные константы с помощью условных последователь-ностей, как, например, \N (новая строка), \T (табуляция), \0(нулевой символ), \\ (обратная косая черта), \' (одинарнаякавычка) и т.д. Хотя они выглядят как два символа, на самомделе являются одним. Кроме того, можно сгенерировать произ-вольную последовательность двоичных знаков размером в байт,если написать '\DDD' где DDD - от одной до трех восьмеричных цифр, как в #DEFINE FORMFEED '\014' /* FORM FEED */ Символьная константа '\0', изображающая символ со значе-нием 0, часто записывается вместо целой константы 0 , чтобыподчеркнуть символьную природу некоторого выражения.

Константное выражение

Константное выражение - это выражение, состоящее из од-них констант. Такие выражения обрабатываются во время компи-ляции, а не при прогоне программы, и соответственно могутбыть использованы в любом месте, где можно использовать кон-станту, как, например в #DEFINE MAXLINE 1000 CHAR LINE[MAXLINE+1]; или SECONDS = 60 * 60 * HOURS;

Строчная константа

Строчная константа - это последовательность, состоящаяиз нуля или более символов, заключенных в двойные кавычки,как, например, "I AM A STRING" /* я - строка */или "" /* NULL STRING */ /* нуль-строка */ Кавычки не являются частью строки, а служат только дляее ограничения. те же самые условные последовательности, ко-торые использовались в символьных константах, применяются ив строках; символ двойной кавычки изображается как \". С технической точки зрения строка представляет собоймассив, элементами которого являются отдельные символы. Что-бы программам было удобно определять конец строки, компиля-тор автоматически помещает в конец каждой строки нуль-символ\0. Такое представление означает, что не накладывается конк-ретного ограничения на то, какую длину может иметь строка, ичтобы определить эту длину, программы должны просматриватьстроку полностью. При этом для физического хранения строкитребуется на одну ячейку памяти больше, чем число заключен-ных в кавычки символов. Следующая функция STRLEN(S) вычисля-ет длину символьной строки S не считая конечный символ \0. STRLEN(S) /* RETURN LENGTH OF S */ CHAR S[]; { INT I; I = 0; WHILE (S[I] != '\0') ++I; RETURN(I); } Будьте внимательны и не путайте символьную константу сострокой, содержащей один символ: 'X' - это не то же самое,что "X". Первое - это отдельный символ, использованный сцелью получения численного значения, соответствующего буквех в машинном наборе символов. Второе - символьная строка,состоящая из одного символа (буква х) и \0.

Описания

Все переменные должны быть описаны до их использования,хотя некоторые описания делаются неявно, по контексту. Опи-сание состоит из спецификатора типа и следующего за нимсписка переменных, имеющих этот тип, как, например, INT LOWER, UPPER, STEP;CHAR C, LINE[1000]; Переменные можно распределять по описаниям любым обра-зом; приведенные выше списки можно с тем же успехом записатьв виде INT LOWER;INT UPPER;INT STEP;CHAR C;CHAR LINE[1000]; Такая форма занимает больше места, но она удобна для до-бавления комментария к каждому описанию и для последующихмодификаций. Переменным могут быть присвоены начальные значения внут-ри их описания, хотя здесь имеются некоторые ограничения.Если за именем переменной следуют знак равенства и констан-та, то эта константа служит в качестве инициализатора, как,например, в CHAR BACKSLASH = '\\';INT I = 0;FLOAT EPS = 1.0E-5; Если рассматриваемая переменная является внешней илистатической, то инициализация проводится только один раз,согласно концепции до начала выполнения программы. Инициали-зируемым явно автоматическим переменным начальные значенияприсваиваются при каждом обращении к функции, в которой ониописаны. Автоматические переменные, не инициализируемые яв-но, имеют неопределенные значения, (т.е. мусор). Внешние истатические переменные по умолчанию инициализируются нулем,но, тем не менее, их явная инициализация является признакомхорошего стиля. Мы продолжим обсуждение вопросов инициализации, когдабудем описывать новые типы данных.

Арифметические операции







Последнее изменение этой страницы: 2016-08-26; Нарушение авторского права страницы

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.83.188.254 (0.008 с.)