Рассылка закрыта
Вы можете найти рассылки сходной тематики в Каталоге рассылок.
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 |
| В избранное | ||
