Программирование для карманных компьютеров
Шрифт:
enum year{JAN,FEB,MAR,APR,MAY,JUN,JUL,AUG,SEP,OCT,NOV,DEC};
Константы в перечислении можно инициализировать значениями, отличными от индексных, которые присваиваются по умолчанию:
enum times{SAVE=10,SLEEP=20,STOP=30};
Если инициализируется только часть элементов перечисления, то те элементы перечисления, которые указаны после инициализированных, будут получать возрастающие значения, отсчитываемые от того значения, которое они получили при инициализации. В следующем фрагменте элемент STOP будет инициализирован значением 21.
enum times{SAVE=10,SLEEP=20,STOP};
Области видимости и имена
Объявление вводит имя в область видимости. Это значит, что имя может использоваться только в определенной части текста программы, и, где именно будет использоваться объявленное имя, зависит от того, в каком месте программы оно было объявлено.
Для имени, объявленного в теле функции ( локальное имя), область видимости начинается с места объявления и заканчивается там, где заканчивается блок, внутри которого было объявлено имя. Блоком считается фрагмент кода, заключенный в фигурные скобки.
Имя называется глобальным, если оно объявлено вне любой функции или класса. Область видимости глобального имени простирается от места объявления
Упражнение 4.1 (продолжение)
19. Добавить в программу код, приведенный в листинге 4.9. Нужно при этом объявить соответствующую функцию и добавить еще одну ветвь case.
Листинг 4.9
// Блок 16
void f4{
//В начале файла объявлена глобальная переменная mm, указывающая на массив
//типа char, то есть на массив символов, то есть на строку. Устанавливая
//первым элементом массива 0, мы показываем, что это строка пустая. Затем,
//при помощи функции strcat, мы добавляем к этой строке строку Hello, Global
//Word! с символом переноса на другую строку \n.
mm[0] = \0;
strcat(mm, «Hello, Global Word! \n»);
//Снова объявляем переменную mm, чем скрываем имя глобальной переменной mm.
//Теперь обращаясь к mm, мы обращаемся к локальному имени, указывающему на
//другую область памяти. В эту другую область мы записываем строку Hello,
//Local Word!
char mm[256];
mm[0] = \0;
strcat(mm, «Hello, Local Word! \n»);
//К строке из локальной переменной mm, мы дописываем строку из глобальной
//переменной mm, обращаясь к глобальной переменной при помощи оператора
//разрешения области видимости::
strcat(mm,mm);
mbstowcs(mstr, mm, 256);
szStr = mstr;
}
Комментарии в тексте поясняют действие кода. После запуска программы нужно нажать клавишу 4. На экран будет выведено следующее сообщение:
Hello, Local Word! Hello, Global Word!
Поскольку ошибки, связанные с ненамеренным замещением имен трудно обнаружить, особенно в большой программе, следует придерживаться следующих правил.
? Чем более глобальное имя было создано, тем более описательный характер, позволяющий понять функциональную нагрузку имени и область, оно должно носить.
? Имена из локальной области видимости хорошо делать однобуквенными.
? Чем чаще используется имя, тем короче его надо делать.
? Имя должно отображать смысл использования объекта, а не детали его представления.
? Нужно записывать имена макросов заглавными буквами.
? Следует отделять слова внутри имени символом подчеркивания.
Объекты и lvalue (левые значения)
Когда для хранения тех или иных данных выделяется некоторая непрерывная область памяти, эта операция создает объект. В С++ разработчик может создавать области памяти и хранить там данные, не присваивая этим объектам имен. Но если вы такому объекту все же присваивается имя, то этим создается так называемое lvalue , то есть нечто, что может быть использовано в левой части оператора присваивания. Когда вы создаете переменную, вы создаете модифицируемое lvalue . При создании константы возникает константное lvalue .
Объект, объявленный в функции, создается в момент его определения и живет до выхода из функции. Такого рода объекты называются автоматическими или локальными . Глобальные объекты, а также статические объекты, объявленные в функциях и классах, живут до тех пор, пока не закончится программа.
Объекты, созданные явно при помощи оператора new, уничтожаются оператором delete, и программист непосредственно управляет временем их жизни. Такие объекты называются динамическими .
typedef
Объявление, начинающееся с ключевого слова typedef, вводит новое имя для типа.typedef char* Pchar;
Эта конструкция создает новое имя для уже имеющегося типа «указатель на символ». Таким образом, ключевое слово typedef позволяет создавать синонимы уже имеющимся типам.
Выражения
Выражения – это операторы, операнды и разделители, определяющие некоторое вычисление и возвращающие значение. В следующем разделе будут рассматриваться основные операторы языка С++, а в этом разделе нужно коснуться приоритета выполнения операторов в выражениях. Правильное понимание того, в каком порядке будут выполняться операторы, поможет избежать многих досадных ошибок, которые не в состоянии обнаружить компилятор. В справочной системе, в разделе, посвященном языку C/C++, есть страница Operator Precedence and Associativity, посвященная этому вопросу. На этой странице указаны практически все операторы языка C++.
Операторы
Операторы – это лексемы, которые производят некоторые вычисления, если их применить к переменным или другим объектам внутри выражения.
Арифметические операторыАрифметические операторы используются для математических вычислений. Они приведены в табл. 4.1.
Инкремент и декремент могут быть как постфиксными, так и префиксными.
Это демонстрирует следующий фрагмент кода:
int x=1, y=0;
y = x++; //Сначала y получит значение x (1), затем x будет увеличен на 1
y = ++x; //Сначала x будет увеличен на 1, затем полученное значение будет
//увеличено на единицуБудет иметь смысл и выражение ++x = 5. А вот выражение x++ = 5 не имеет смысла, поскольку мы пытаемся присвоить значение 5 операции инкремента. Таблица 4.1. Арифметические операторы
Битовые операторы приведены в следующем списке.
? & – побитовое И. Если оба бита равны 1, то результат тоже будет равен 1, иначе результат будет равен 0.
? | – побитовое ИЛИ. Оператор сравнивает два бита и возвращает 1, если хотя
? ^ – побитовое исключающее ИЛИ. Оператор сравнивает два бита и возвращает 1 только тогда, когда один из битов равен 0, а другой – 1, иначе результат будет равен 0.
? ~ – побитовая инверсия, при которой значение каждого бита меняется на противоположное.
«– побитовый сдвиг вправо. В этом случае последний бит теряется, для беззнакового значения слева вдвигается 0, для знакового – расширяется знак.
? «– побитовый сдвиг влево. В этом случае левый бит теряется, а справа вдвигается ноль.
Тернарный условный оператор Оператор? имеет три операнда. Пример его применения показан ниже.Е1?Е2:ЕЗ
Первым выполняется операнд Е1. Если результат его выполнения равен true, то выполняется операция Е2, а ЕЗ игнорируется. Если результат выполнения Е1 равен false, то выполняется ЕЗ, а Е2 игнорируется. Например, в коротком выражении а = (х>у)?х: у переменная а всегда будет получать большее значение. Операторы сравнения и равенства
Операторы сравнения и равенства приведены в табл. 4.2.
Выполнение этих операторов между двумя операндами возвращает логический результат true, если условие выполняется, или значение false, если оно не выполняется. Операторы == и!= могут быть использованы для сравнения указателей, в то время как остальные операторы для этого использовать нельзя.
Таблица 4.2. Операторы сравнения и равенстваЛогические операторы языка C++ приведены в табл. 4.3.
Таблица 4.3. Логические операторыОператор * предназначен для объявления указателя. Указатель содержит в себе адрес блока памяти, на который он указывает. Этот же оператор разыменовывает указатель, то есть позволяет получить доступ к содержимому объекта, на который создан указатель.
Оператор & (адрес) предназначен для получения адреса, по которому содержится значение конкретной переменной. Когда мы обращаемся к переменной по имени, мы всегда получаем доступ к ее значению, но не к области памяти, в которой это значение хранится. Иногда надо знать, в какой конкретно области памяти хранится тот или иной объект. В этом случае следует использовать оператор разыменования.
Другие операторы? – скобки. Они позволяют группировать выражения, обеспечивая им высший приоритет исполнения, выделять выражения проверки условия в операторах ветвления или цикла. Также скобки показывают, что определенное имя является функцией и заключают в себе параметры функций. Иногда скобки обозначают операцию явного приведения типа.
? {} – фигурные скобки. Они предназначены для обозначения начала и конца составного выражения, объединяющего несколько простых выражений.
? [] – квадратные скобки служат для объявления массивов.
? sizeof – возвращает число типа int, показывающее объем памяти в байтах, занимаемый операндом. Операнд может быть любым выражением, именем типа или объекта.
?. – точка, предназначена для выбора члена структуры или объединения в выражении типа s.m, где s – объект класса структуры или объединения, а m – член структуры или объединения.
? – > стрелка, предназначена для выбора члена структуры или объединения в выражении типа s->m, где s – указатель на объект класса структуры или объединения, а m – член структуры или объединения.
Специфичные операторы C++?:: доступ к объекту-владельцу данного объекта, классу-владельцу данного члена или разрешение области видимости. Доступ к объекту-владельцу данного объекта для динамических объектов или к классу-владельцу для статических объектов будет рассматриваться позже.
?.* – разыменование указателя на член класса.
? – >* – разыменование указателя на указатель члена класса.
? const_cast – добавляет или удаляет из имени указателя модификатор const, когда указатель, имеющий такой модификатор, надо передать в качестве аргумента функции.
? dynamic_cast – во время выполнения программы проверяет, может ли быть указатель приведен к определенному типу или выполняет такое приведение.
? reinterpret_cast – преобразует типизированный указатель в указатель на пустой тип и обратно.
? static_cast – преобразует любой тип, известный на момент компиляции в любой другой тип, также полностью известный на момент компиляции. В том случае, если преобразование может быть выполнено другими средствами языка (например, приведение типа intк типу double), результат применения static_cast будет тем же самым.
? typeid – получает идентификатор времени исполнения для любого выражения-операнда.
? new – осуществляет динамический захват памяти во время исполнения.
? delete – динамически освобождает память, захваченную командой new.
? this – оператор указания на объект, для которого была вызвана данная функция.
? ~ – деструктор класса.
Инструкции
В группу инструкций в С++ выделено все, что влияет на ход выполнения программы и порядок выполнения выражений. В том числе инструкцией считается последовательность выражений, оканчивающаяся точкой с запятой. Таким образом, в число инструкций попадают выражения присваивания и вызовы функций. Особым случаем инструкции является пустая инструкция, которая ничего, кроме точки с запятой, не содержит. Функционально такая инструкция особой пользы не несет, но может быть полезна при отладке или, к примеру, в организации бесконечного цикла.
if…else Эта инструкция позволяет выполнять некоторые выражения только в случае, когда выполняется некоторое условие. Имеет две формы: сокращенную и полную. Синтаксис сокращенной формы приведен ниже.if (<condition>) <statement1>;
Полная форма выглядит несколько иначе.
if (<condition>) <statement1>; else <statement2>;
Если (if) условие в скобках (<condition>) в результате вычисления дает результат типа bool со значением true, то выполняется выражение <statement1>, иначе будет выполнено выражение <statement2>. Пример использования этой конструкции приведен в листинге 4.10. Листинг 4.10
void fother {
char mstr[20];
mstr[0]= \0;
int a = 5;
if (a>5) //Если a>5
{
strcat(mstr, «a>5»); //содержимым строки будет «a>5»
}
else //иначе
{
if (a =5) //Если а=5
{
strcat(mstr, «a=5»); //содержимым строки будет «a=5»
}
else //иначе
{
strcat(mstr, «a<5»); //содержимым строки будет «a<5»
};
};
}