|
Программирование >> Процедурные приложения
осуществит глобальную замену в программном коде имени sales team числом 10. Причем никакие другие значения идентификатору sales team не могут быть присвоены, поскольку переменная с таким именем в программе формально не описана. В результате идентификатор sales team может использоваться в программе в качестве константы. Обратите внимание, что строка с директивой #define не заканчивается точкой с запятой. После числа 10 этот символ будет воспринят как часть идентификатора, в результате чего все вхождения SALES TEAM будут заменены литералом 10;. Итак, мы рассмотрели два способа создания констант: с помощью квалификатора const и директивы #define. В большинстве случаев они дают одинаковый результат, хотя имеется и существенное различие. Директива #define создает макроконстанту, и ее действие распространяется на весь файл. С помощью же ключевого слова constсоздается переменная. Далее в этой главе при рассмотрении классов памяти мы узнаем, что область видимости переменной можно ограничить определенной частью программы. Это же относится и к переменным, описанным с помощью квалификатора const. Таким образом, последний дает программисту больше гибкости, чем директива #define. Квалификатор volatile Ключевое слово volatile указывает на то, что данная переменная в любой момент может быть изменена в результате выполнения внешних действий, не контролируемых программой. Например, следующая строка описывает переменную event time, значение которой может измениться без ведома программы: volatile int event time; Подобное описание переменной может понадобиться в том случае, когда переменная event time обновляется системными устройствами, например таймером. При получении сигнала от таймера выполнение программы прерывается и значение переменной изменяется. Квалификатор volatile также применяется при описании объектов данных, совместно используемых разными процессами в многозадачной среде. Одновременное применение квалификаторов const и volatile Допускается одновременное употребление ключевых слов const и volatile при объявлении переменных. Так, в следующей строке создается переменная, обновляемая извне, но значение которой не может быть изменено самой программой: const volatile constant event time; Таким способом реализуются два важных момента. Во-первых, в случае обнаружения компилятором выражения, присваивающего переменной соnstant event time какое-нибудь значение, будет выдано сообщение об ошибке. Во-вторых, компилятор не будет выполнять оптимизацию, связанную с подстановкой вместо адреса переменной constant event time ее действительного значения, поскольку во время выполнения программы это значение в любой момент может быть изменено. Преобразования типов данных До сих пор в рассмотренных примерах мы в отдельно взятых выражениях использовали переменные только одного типа данных, например intили float.Но часто бывают случаи, когда в операции участвуют переменные разных типов. Такие oперации называются смешанными. В отличие от многих других языков программирования, языки С и C++ могут автоматически преобразовывать данные из одного ипа в другой. Данные разных типов по-разному сохраняются в памяти. Возьмем число 10. Формат, в котором оно будет хранится, зависит от назначенного этому числу типа данных. Другими словами, сочетание нулей и единиц в представлении одного и того же числа 10 будет разным в зависимости о того, интерпретируется ли оно как целое или как число с плавающей запятой. Давайте рассмотрим следующее выражение, где для двух переменных, fresultifvalue, задан тип данных float, а для переменной ivalue - тип int: Iresult = fvalue * ivalue; Это типичный пример смешанной операции, в процессе которой компилятор штоматически выполняет определенные преобразования. Целочисленное значение переменной ivalue будет прочитано из памяти, приведено к типу с плавающей запятой, умножено на исходное значение переменной fvalue, и результат, также в шде значения с плавающей запятой, будет сохранен в переменной fresult. Обратите шимание на то, что значение переменной iivalue при этом никак не меняется, ставаясь целочисленным. Автоматические преобразования типов данных при выполнении смешанных операций производятся в соответствии с иерархией преобразований. Суть состоит в гом, что с целью повышения производительности в смешанных операциях значения эазных типов временно приводятся к тому типу данных, который имеет больший приоритет в иерархии. Ниже перечислены типы данных в порядке уменьшения приоритета: double float long int short Если значение преобразуется к типу, имеющему большую размерность, потери информации не происходит, вследствие чего не страдает точность вычислений. Посмотрим, что происходит в случае приведения значения типа int к типу float. Предположим, переменные ivaluel и ivalue2 имеют тип int, а переменные fvalue и fresult - тип float. Выполним следующие операции: ivaluel = 3; ivalue2 = 4; fvalue = 7.0; fresult = fvalue + ivaluel/ivalue2; Выражение ivaluel/ivalue2 не является смешанной операцией: это деление двух целых чисел, результатом которого будет ноль, поскольку дробная часть (в данном случае 0,75) отбрасывается. Таким образом, переменной fresult будет присвоено значение 7,0. Как изменится результат, если переменная ivalue2 будет описана как float? В таком случае операция ivaluel/ivalue2 станет смешанной. Компилятор автоматически приведет значение переменной ivaluel к типу float - 3,0, и результат деления будет 0,75. В сумме с переменной fvalue получим 7,75. Важно помнить, что тип переменной, находящейся слева от оператора присваивания, предопределяет тип результата вычислений. Предположим, что переменные fx и fy описаны как float, а переменная iresuit - как int. Рассмотрим следующий фрагмент: fx = 7.0; fy = 2.0; iresult = 4.0+ fx/fy; Результатом выполнения операции fx/fy будет 3,5. Можно предположить, что переменной iresult будет присвоена сумма 3,5 + 4,0 = 7,5. Но, поскольку это целочисленная переменная, компилятор преобразует число 7,5 в целое, отбрасывая дробную часть. Полученное значение 7 и присваивается переменной iresult. Явное преобразование типов Иногда возникают ситуации, когда необходимо изменить тип переменной, не дожидаясь автоматического преобразования. Этой цели служит специальный оператор приведения типа. Если где-либо в программе необходимо временно изменить тип переменной, нужно перед ее именем ввести в круглых скобках название соответствующего типа данных. Например, если переменные ivaluel и ivalue2 имеют тип int., а переменные fvalue и fresult - тип float, то благодаря явному преобразованию типов в следующих трех выражениях будут получены одинаковые результаты: fresult = fvalue+(float)ivaluel/ivalue2; fresult = fvalue+ivaluel/(float)ivalue2; fresult = fvalue+(float)ivaluel/(float)ivalue2; Во всех трех случаях перед выполнением деления происходит явное приведение значения одной или обеих переменных к типу float. Даже если преобразованию подвергается только одна переменная, как мы уже знаем, в операции деления к типу float будет автоматически приведен и результат. Классы памяти В Visual C/C++ имеется четыре спецификатора класса памяти: auto register static extern Спецификатор класса памяти может предшествовать объявлениям переменных и функций, указывая компилятору, как следует хранить переменные в памяти и как получать доступ к переменным или функциям. Переменные, объявленные со спецификаторами auto или register, являются локальными, а со спецификаторами static и extern - глобальными. Память для локальной переменной выделяется заново всякий раз, когда выполнение программы достигает блока, в котором объявлена переменная, и удаляется по завершении выполнения этого блока. Память для глобальной переменной выделяется один раз при запуске программы и удаляется по завершении программы. Указанные четыре спецификатора определяют также область видимости переменных и функций, т.е. часть программы, в пределах которой к идентификатору можно обратиться по имени. На область видимости переменной и функции влияет место ее объявления в программе. Если объявление расположено вне любой функции, то говорят о внешнем уровне объявления. Если же оно находится в теле функции, то говорят о внутреннем уровне объявления. Смысл спецификаторов класса памяти несколько различается в зависимости от того, дается ли объявление переменной или функции и на внешнем или внутреннем уровне объявляется данный идентификатор. Объявление переменных на внешнем уровне Переменная, объявленная на внешнем уровне, является глобальной и по умолчанию имеет класс памяти extern. Внешнее объявление может включать инициализацию (явную либо неявную) или просто быть ссылкой на переменную, инициализируемую в другом месте программы. static int ivaluel; поумолчанию неявно присваивается static int ivalue1 = 10; явное присваивание int ivalue2 =20; явное присваивание Область видимости глобальной переменной распространяется до конца файла. Обращение к переменной не может находиться выше той строки, где она была объявлена. Переменная объявляется на внешнем уровне только один раз. Если в одном из файлов создана переменная с классом памяти static,то она может быть объявлена под тем же именем с тем же спецификатором static в любом другом исходном файле. Так как статические переменные доступны только в пределах своего файла, конфликтов имен не возникнет. С помощью спецификатора extern можно объявить переменную, которая будет доступна из любого места программы. Это может быть ссылка на переменную, описанную в другом файле или ниже в том же файле. Последняя особенность делает возможным размещение ссылок на переменную до того, как она будет инициализирована. В следующем примере программы на языке C++ демонстрируется использование ключевого слова extern: Файл А #include <iostream.h> extern int ivalue ;
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |