Рассылка закрыта
Вы можете найти рассылки сходной тематики в Каталоге рассылок.
C и C++ для начинающих
Доброго времени суток! Сегодня речь пойдет о базовых правилах языка. 1. Комментарии в языке С заключаются в пары символов /* и /. Все, что расположено между ними, игнорируется компилятором. Вложенные комментарии не допускаются: / Какие-то комментарии /* Еще комментарии */ И еще комментарии / ^ Здесь комментарии А здесь ^ ^ Синтаксическая начинаются заканчиваются ошибка Комментарии в С могут быть многострочными. 2. Сторонники Паскаля! Запомните: язык С ЧУВСТВИТЕЛЕН К РЕГИСТРУ! MyIdent и myident - это два разных идентификатора (да, ИДЕНТИФИКАТОР - это набор букв, цифр и знака подчеркивания, начинающийся с буквы или знака подчеркивания и не совпадающий с ЗАРЕЗЕРВИРОВАННЫМ СЛОВОМ. О них зарезервированных словах) позже). 3. Я думаю, не существует такого языка, в котором нет переменных. ПЕРЕМЕННАЯ - это некоторая область для хранения данных, с которыми работает программа. Переменная характеризуется следующими параметрами: 1. ИМЕНЕМ - имя переменной представляет собой идентификатор, по которому вы в дальнейшем будете обращаться к ней; 2. ТИПОМ - тип переменной задает характер информации, хранящейся в ней, например, целое число, дробное число, строка символов и т.д. 3. ОБЛАСТЬЮ ВИДИМОСТИ - задается неявно и указывает на те части кода, при выполнении которых переменная будет доступна; 4. Собственно значением переменной; 5. АДРЕСОМ переменной в памяти. Последний пункт почему-то часто пропускают, хотя он является не менее важнам, чем остальные - после компиляции программы все имена переменных, как и функций (о них позже) будут убраны и заменены адресами. О роли адреса мы поговорим позже. ВСЕ ПЕРЕМЕННЫЕ В ЯЗЫКЕ С ДОЛЖНЫ БЫТЬ ОБЪЯВЛЕНЫ! Любители Бейсика, забудьте о том, чтобы использовать большую кучу переменных без объявления! В принципе, объявлять переменные до их использования - это просто правило хорошего тона. Кроме того, оно позволяет компилятору разделить типы, переменные и функции. Переменные в С объявляются следующим образом: [модификатор_типа] тип_переменной имя_переменной [= начальное значение] [, имя_переменной [= начальное_значение]... ]; Примеры: int a; int a = 5; int a, b; int a, b = 3; int a = 2, b = 3, c = 4; Типов в языке С немного. Перечислю их все: void int char fload double Все. Как видите, не такое уж и разнообразие. Но, как показывает практика, этих пяти типов более чем достаточно. Более подроюно о каждом из них. void Фиктивный тип. Размер значения типа void принимается равным нулю, поэтому вы не можете объявлять переменные такого типа. Тем не менее, этот тип находит широкое применение, о котором позже. int Обычное знаковое целое число. Его размер может быть равным 16 или 32 бита, в зависимости от разрядности платформы, для которой компилируется программа. char Разновидность типа int. Его размер составляет 8 бит, так что чаще всего он используется для хранения символов. Однако, ничего не запрещает вам хранить в нем целые числа, или, наоборот, использовать для хранения символов тип int. float Вещественное число одинарной точности (32 бита). double Вещественное число двойной точности (64 бита). Модификаторы типа: short Явно указывает компилятору, что под данную переменную необходимо отвести 2 байта, независимо от разрядности платформы. Я ни разу не использовал данный модификатор с типом, отличным от int, поэтому тут ничего сказать не смогу. long Явно указывает компилятору, что под данную переменную необходимо отвести 4 байта, независимо от разрядности платформы. Я ни разу не использовал данный модификатор с типом, отличным от int, поэтому тут ничего сказать не смогу. signed Указывает компилятору, что данная переменная является знаковой (то есть может принимать как положительные, так и отрицательные значения). Не может использоваться с типами float и double. unsigned Указывает компилятору, что данная переменная является беззнаковой (то есть может принимать только положительные значения). Не может использоваться с типами float и double. Типы short int, long int, signed int, unsigned int разрешается сокращать соответственно до short, long, signed и unsigned. Обратите внимание: тип char может являться как знаковым, так и беззнаковым, в зависимости от конкретного компилятора. Поэтому, чтобы быть уверенным в допустимых значениях, используйте типы signed char и unsigned char. Тип int по умолчанию является знаковым. Да, и еще: все указанные слова, а именно: int, char, float, double, void, short, long, signed, unsigned - являются зарезервированными словами. То есть вы не можете объявить переменную с именем char. Но если очень хотите - можете объявить ее с именем Char - как я уже говорил, язык С чувствителен к регистру. 3. ВСЕ ЯВЛЯЕТСЯ ОПЕРАТОРОМ! Ну, или почти все :) Принципиальная разница С и других языков в том, что в С все операторы равноправны. Скажем (для тех, кто имеет некоторый опыт в программировании на других языках), что вызов функции тоже являтеся оператором. Более того, каждый оператор (исключений нет!) возвращает некоторое значение - результат своей работы. Ну, для оператора сложения все понятно: оператор a + b возвратит сумму чисел a и b. А что возвращает оператор присваивания (в С он записывается как = )? Оказывается, значение выражения a = b равно a (или b, что неважно, так как после выполнения оператора значения a и b равны). Эта на первый взгляд бессмысленная возможность, во-первых, сильно упростила создание языка (нет необходимости разделять операторы на возвращающие значение и нет, да еще проверять на правильность. Например, на Паскале (кто знает) необхдимо специально проверять выражение на предмет выражений вроде a := (b := c) ), а во-вторых, позволила сильно сократить размер исходного текста программы. Например: a = b = c = d = 0; как будет работать такой участок кода? Начнем сначала. Данное выражение присваивает переменной a результат выполнения оператора b = c = d = 0, который, в свою очередь, присваивает переменной b результат выполнения оператора c = d = 0, который... То есть этот участок кода как бы развертывается в такой: d = 0; c = d; b = c; a = b; Итак, как мы видим, всем четырем переменным присвоено начальное значение всего одним оператором. Впечатляет? :) Как известно, операции различаются по приоритету. Как и в остальных языках программирования, приоритет операций можно явно указывать при помощи скобок. Вообще в языке С очень много операторов. Вот те из них, которые нам понадобятся на начальных порах: Примечание: в С истиной (true) считается всякое ненулевое значение, ложью (false) - нуль. a = b Присваивает переменной a значение переменной b и возвращает присвоенное значение. a + b Возвращает сумму операндов. a - b Возвращает разность операндов. a b Возвращает произведение операндов. a / b Возвращает частное операндов. Обратите внимание: частное двух целых чисел является целым числом! Например, 9 / 2 = 4. a % b Возвращает остаток от деления a на b. a << b Возвращает a * 2^n (2^n здесь - n-ная степень числа 2). a >> b Возвращает a / 2^n (2^n здесь - n-ная степень числа 2). a & b Возвращает результат побитовой операции "и" (надеюсь все знают, что это такое. Если кто не знает - пишите, в следующий раз объясню) над операндами. a | b Возвращает результат побитовой операции "или" над операндами. a ^ b Возвращает результат побитовой операции "исключающее или" над операндами. ~a Возвращает результат побитовой операции "не" над операндом. a == b Возвращает true, если значения переменных a и b равны, и false в противном случае. a < b Возвращает true, если значения переменной a меньше, чем b, и false в противном случае. a > b Возвращает true, если значения переменной a больше, чем b, и false в противном случае. a && b Возвращает true, если оба операнда содержат true, и false в противном случае (логическое И). a || b Возвращает true, если хоть один из операндов содержат true, и false в противном случае (логическое ИЛИ). !a Возвращает true, если a содержит false, и false в противном случае (логическое НЕ) Для следующих операторов я приведу их альтернативный вариант записи: a != b ! (a == b) a <= b ! (a > b) a >= b ! (a < b) a += b a = a + b a -= b a = a - b a = b a = a b a /= b a = a / b a %= b a = a % b a &= b a = a & b a |= b a = a | b a ^= b a = a ^ b a <<= b a = a >> b a >>= b a = a << b a++ a = a + 1 ++a a = a + 1 a-- a = a - 1 --a a = a - 1 Обратите внимание на префиксную (++a, --a) и постфиксную (a++, a--) форму записи последних операторов. Хоть все они имеют наивысший приоритет, но операторы ++a и --a выполнятся в первую очередь, а a++ и a-- - в последнюю: int a = 1, int a = 1, b = 2, b = 2, c; c; c = a + ++b; c = a + b++; /* c = 4, a = 1, b = 3 / / c = 3, a = 1, b = 3 */ 4. Следующей структурной единицей после выражения является ФУНКЦИЯ. Функция - это некоторый участок кода, который выполняет некоторые действия и возвращает, как и оператор, некоторое значение - результат своей работы. В отличие от операторов, функции могут не возвращать значения. Такие функции ценны своим побочным эффектом - например, функция clrscr очищает экран (в DOS), но, как можно догадаться, ничего при этом не возвращает (считается, что в этом случае функция возвращает тип void. Вот вам и одно из обещанных применений). Функция описывается так: тип_возвращаемого_значения имя_функции ([список_параметров]) { описание_локальных_переменных операторы return возвращаемое_значение; } Список параметров выглядит так: тип_параметра имя_параметра[, тип_параметра имя_параметра[, ...]] Или так: void Если после списка параметров следует многоточие (например: int myfunc (char a, ...)), то после всех описанных параметров может следовать любое количество любых параметров. Обратите внимание на такое описание функции: int myfunc () С будет трактовать такое описание как int myfunc (...), а С++ - как int myfunc (void). Пример: функция, возвращающая значение полинома 3*x*x + 2*x + 1: int polynom (int x) { int a, b, c; a = 3 x x; b = 2 * x; c = 1; return a + b + c; } Эту же функцию можно переписать несколько покороче: int polynom (int x) { return 3*x*x + 2*x + 1; } Остановимся поподробнее на зарезервированном слове return. После него функция перестает выполняться и возвращает управление вызвавшей ее функции, передав значение, указанное после return, как результат. Слов return в функции может быть несколько, но хотя бы одно должно присутствовать обязательно. Исключение - когда функция имеет тип возвращаемого значения void. В этом случае слово return в функции может и отсутствовать, если оно есть, то оно не должно передавать что-либо в качестве результата. В этом случае слово записывается так: return; Вы можете описать функцию, не задав ее тело. Это необходимо, если две функции ссылаются друг на друга (так называемая взаимная рекурсия): int func1 (int a); int func2 (int a) { return func1 (a); } int func1 (int a) { return func2 (a); } Этот самый простой пример приведет к зацикливанию: функции будут вызывать друг друга бесконечно до исчерпания свободной памяти. Но в жизни иногда приходится иметь дело с взаимной рекурсией. Да, и еще: локальные переменные функции существуют только во время выполнения этой функции. Они создаются всякий раз при входе в функцию и уничтожаются всякий раз при выходе из нее. Глобальные переменные (т.е. те, которые были описаны вне какой-либо функции) существуют все время и в единственном экземпляре на всю программу. Старайтесь не использовать глобальные переменные там, где без этого можно обойтись - этим вы обеспечите независимость функций друг от друга и повысите надежность программы. 5. В программе обязательно должна присутствовать функция int main (void). Именно с нее начинается выполнение программы. Когда функция main завершает свою работу, программа прекращает выполнение и выставляет переменную errorlevel (кто не знает - читайте описание DOS) (или код возврата, что одно и то же) на значение, возвращенное функцией. 6. Функции могут вызывать друг друга. Пример (с написанной ранее функцией): int a, b; a = 4; b = myfunc (a); Рассмотрим еще один пример. void myfunc (void) { /* Неважно, что она делает / } int main (void) { myfunc (); return 0; } Сторонники Паскаля! Обратите внимание на разницу между mufunc и myfunc(). myfunc - это ФУНКЦИЯ, а myfunc() - это РЕЗУЛЬТАТ ЕЕ РАБОТЫ. Поэтому если вы напишете: myfunc; - то ошибки компиляции не будет (в выражениях допускается отсутствие операторов), но ничего не произойдет - для того, чтобы вызвать функцию, необходимо подействовать на нее оператором вызова функции () (я о нем писал ранее). Функция может вызывать саму себя (т.н. рекурсия). Часто это бывает полезно. Пример: int func (int a) { return a func (a - 1); } Многие увидят в этой функции функцию вычисления факториала числа. К сожалению, ей не хватает условия, по которому останавливаться. Об условиях - в следующий раз. Функции в С совершенно равноправны. И функция main тоже может вызываться другими функциями: int func (int a); int main (void) { return func (5); } int func (int a) { return main (); } В этом случае выход из программы, конечно, произойдет только после завершения работы "самой наружной" функции main. 7. В языке с нет предопределенных функций. Каждая используемая функция должна быть где-то определена до ее использования. Но самому писать многие требуемые функции (ввод-вывод, файлы, и т.д.) каждый раз несколько скучно :) К счастью, С снабжен библиотекой, содежращей в себе множество разнообразных функций. Для того, чтобы использовать ее, подключите к вашей программе требуемый ЗАГЛОВОЧНЫЙ ФАЙЛ (он имеет расширение .h) к вашей программе следующей строкой: #include <имя_файла.h> На место этой строки в программу при компиляции будет позставлено содержание указанного файла. На первых порах нам понадобится только функция printf, содержащаяся в заголовочном файле stdio.h и осуществляющая простой вывод на экран. Вызывать мы ее пока что будем так: printf ("Hello, world\n"); printf ("%d + %d = %d\n", i, i, i + i); С первым примером все ясно. Сложнее со вторым. printf принимает в качестве первого параметра строку, в которой на месте последовательностей %x, где х - одно из: d, с, f, s, печатаются параметры по очереди в формате (соответственно) целого числа, символа, вещественного числа или строки символов. \n в конце строки трансформируется в символ "новая строка". Домашнее задание: 1. Еще раз внимательно прочитать программу "Hello, world" из первого выпуска и понять ее. 2. Разобраться, что получится в результате выполнения следующего участка кода: int a = 1, b = 2, c = 3, d = 4, e = 5, f, g = 6, h = 8, i; f = (++a + b * (c = d) - (g == h)); i = 3 < 2 < 1; 3. Напишите программу решения квадратного уравнения, считая, что уравнение невырождено и имеет корни. За сим вроде все. Тема следующего выпуска - управляющие конструкции языка. Да встречи! Ведущий рассылки, av
http://subscribe.ru/
E-mail: ask@subscribe.ru |
В избранное | ||