ГЛАВА 2. Базовые средства языка Си

Любая программа, написанная на языке высокого уровня, состоит из последовательности инструкций, оформленных в строгом соответствии с набором правил, составляющих синтаксис данного языка.

При создании программ разработчик может допустить следующие ошибки: синтаксические и логические.

Синтаксические ошибки – это результат нарушения формальных правил написания программы на конкретном языке программирования.

Логические ошибки разделяются, в свою очередь, на ошибки алгоритма и семантические ошибки.

Причиной ошибки алгоритма является несоответствие построенного алгоритма ходу получения конечного результата сформулированной задачи.

Причина семантической ошибки – неправильное понимание смысла (семантики) операторов выбранного языка программирования.

Алфавит языка Си

Алфавит любого языка составляет совокупность символов – тех неделимых знаков, при помощи которых записываются все тексты на данном языке.

Каждому из множества значений, определяемых одним байтом (от 0 до 255), в таблице знакогенератора ЭВМ ставится в соответствие символ. По кодировке фирмы IBM символы с кодами от 0 до 127, образующие первую половину таблицы знакогенератора, построены по стандарту ASCII и одинаковы для всех компьютеров, вторая половина символов (коды 128 – 255) может отличаться и обычно используется для размещения символов национального алфавита. Коды 176 – 223 отводятся под символы псевдографики, а коды 240 – 255 – под специальные знаки (прил. 1).

Алфавит языка Си включает:

– прописные и строчные буквы латинского алфавита и знак подчеркивания (код 95);

– арабские цифры от 0 до 9;

– специальные символы, смысл и правила использования которых будем рассматривать по тексту;

– пробельные (разделительные) символы: пробел, символы табуляции, перевода строки, возврата каретки, новой страницы и новой строки.

Лексемы

Из символов алфавита формируются лексемы (или элементарные конструкции) языка – минимальные значимые единицы текста в программе:

– идентификаторы;

– ключевые (зарезервированные) слова;

– знаки операций;

– константы;

– разделители (скобки, точка, запятая, пробельные символы).

Границы лексем определяются другими лексемами, такими как разделители или знаки операций, а также комментариями.

Идентификаторы и ключевые слова

Идентификатор (ID) – это имя программного объекта* (константы, переменной, метки, типа, функции и т.д.). В идентификаторе могут использоваться латинские буквы, цифры и знак подчеркивания; первый символ ID – не цифра; пробелы внутри ID не допускаются.

Длина идентификатора определяется выбранной версией среды программирования. Например, в среде Borland C++ 6.0 идентификаторы могут включать любое число символов, из которых воспринимаются и используются только первые 32 символа. Современная тенденция – снятие ограничений длины идентификатора.

При именовании объектов следует придерживаться общепринятых соглашений:

– ID переменных и функций обычно пишутся строчными (малыми) буквами – index, max();

– ID типов пишутся с большой буквы, например, Spis, Stack;

– ID констант (макросов) – большими буквами – INDEX, MAX_INT;

– идентификатор должен нести смысл, поясняющий назначение объекта в программе, например, birth_date – день рождения, sum – сумма;

– если ID состоит из нескольких слов, как, например, birth_date, то принято либо разделять слова символом подчеркивания, либо писать каждое следующее слово с большой буквы – birthDate.

В Си прописные и строчные буквы – различные символы. Идентификаторы Name, NAME, name – различные объекты.

Ключевые (зарезервированные) слова не могут быть использованы в качестве идентификаторов.

Список ключевых слов, определенных в стандарте ANSI Cи:

auto do goto signed unsigned
break double if sizeof void
case else int static volatile
char enum long struct while
const extern register switch
continue float return typedef
default for short union

Комментарии

Еще один базовый элемент языка программирования – комментарий – не является лексемой. Внутри комментария можно использовать любые допустимые на данном компьютере символы, поскольку компилятор их игнорирует.

В Си комментарии ограничиваются парами символов /* и */, а в С++ был введен вариант комментария, который начинается символами // и заканчивается символом перехода на новую строку.

Простейшая программа

Программа, написанная на языке Си, состоит из одной или нескольких функций, одна из которых имеет идентификатор main* – главная (основная). Она является первой выполняемой функцией (с нее начинается выполнение программы) и ее назначение – управлять работой всей программы (проекта).

Общая структура программы на языке Си имеет вид:

<директивы препроцессора>

<определение типов пользователя – typedef>

<описание прототипов функций>

<определение глобальных переменных>

<функции>

В свою очередь, каждая функция имеет следующую структуру:

<класс памяти> <тип> < ID функции> (<объявление параметров>)

{ – начало функции

код функции

} – конец функции

Код функции является блоком и поэтому заключается в фигурные скобки.

Функции не могут быть вложенными друг в друга.

Рассмотрим кратко основные части общей структуры программ.

Перед компиляцией программа обрабатывается препроцессором (прил. 3), который работает под управлением директив.

Препроцессорные директивы начинаются символом #, за которым следует наименование директивы, указывающее ее действие.

Препроцессор решает ряд задач по предварительной обработке программы, основной из которых является подключение (include) к программе так называемых заголовочных файлов (обычных текстов) с декларацией стандартных библиотечных функций, использующихся в программе. Общий формат ее использования

#include < ID_файла.h>

где h – расширение заголовочных файлов.

Если идентификатор файла заключен в угловые скобки (< >), то поиск данного файла производится в стандартном каталоге, если – в двойные кавычки (” ”), то поиск файла производится в текущем каталоге.

К наиболее часто используемым библиотекам относятся:

stdio.h – содержит стандартные функции файлового ввода-вывода;

math.h – математические функции;

conio.h – функции для работы с консолью (клавиатура, дисплей).

Второе основное назначение препроцессора – обработка макроопре­делений. Макроподстановка определить (define) имеет общий вид

#define ID строка

Например: #define PI 3.1415927

– в ходе препроцессорной обработки программы идентификатор PI везде будет заменяться значением 3.1415927.

Рассмотрим пример, позволяющий понять простейшие приемы программирования на языке Си:

#include <stdio.h>

void main(void)

{ // Начало функции main

printf(“ Высшая оценка знаний – 10 !”);

} // Окончание функции main

Отличительным признаком функции служат скобки ( ) после ее идентификатора, в которые заключается список параметров. Перед ID функции указывается тип возвращаемого ею результата. Если функция не возвращает результата и не имеет параметров, указывают атрибуты void – отсутствие значений.

Для начала будем использовать функцию main без параметров и не возвращающую значения.

Код функции представляет собой набор инструкций, каждая из которых оканчивается символом «;». В нашем примере одна инструкция – функция printf, выполняющая вывод данных на экран, в данном случае – указанную фразу.

__________________________________________________________________

Приемы отладки в среде программирования Visual C++ 6.0 рассматриваются в прил. 5.

__________________________________________________________________

Основные типы данных

Данные в языке Си разделяются на две категории: простые (скалярные), будем их называть базовыми, и сложные (составные) типы данных.

Тип данных определяет:

– внутреннее представление данных в оперативной памяти;

– совокупность значений (диапазон), которые могут принимать данные этого типа;

– набор операций, которые допустимы над такими данными.

Основные типы базовых данных: целый – int (integer), вещественный с одинарной точностью – floatи символьный – char (character).

В свою очередь, данные целого типа могут быть короткими – short, длинными – long и беззнаковыми – unsigned, а вещественные – с удвоенной точностью – double.

Сложные типы данных – массивы, структуры – struct, объединения – union, перечисления – enum.

Данные целого и вещественного типов находятся в определенных диапазонах, т.к. занимают разный объем оперативной памяти (табл. 2.1).

Таблица 2.1

Тип данных Объем памяти (байт) Диапазон значений
сhar –128 … 127
int 2 (4)* –32768 … 32767
short 1 (2)* –32768 … 32767(–128 … 127)
long –2147483648 … 2147483647
unsigned int 0 … 65535
unsigned long 0 … 4294967295
float 3,14×10–38 … 3,14×1038
double 1,7×10–308 … 1,7×10308
long double 3,4×10–4932 … 3,4×104932

* Размер памяти зависит от разрядности процессора, для 16-разрядных объем памяти определяется первой цифрой, для 32-разрядных – второй.

Декларация объектов

Все объекты, с которыми работает программа, необходимо декларировать, т.е. объявлять компилятору об их присутствии. При этом возможны две формы декларации:

– описание, не приводящее к выделению памяти;

– определение, при котором под объект выделяется объем памяти в соответствии с его типом; в этом случае объект можно инициализировать, т.е. задать его начальное значение.

Кроме констант, заданных в исходном тексте, все объекты программы должны быть явно декларированы по следующему формату:

<атрибуты> <список ID объектов>;

элементы списка ID объектов разделяются запятыми, а атрибуты – разделителями, например: int i, j, k; float a, b;

Объекты программы могут иметь следующие атрибуты:

класс памяти – характеристика способа размещения объектов в памяти (статическая, динамическая); определяет область видимости и время жизни переменной (по умолчанию – auto), данные атрибуты будут рассмотрены в гл. 12;

тип – тип будущих значений декларируемых объектов (по умолчанию устанавливается тип int).

Класс памяти и тип – атрибуты необязательные и при отсутст­вии одного из них (но не обоих одновременно) устанавливаются атрибуты по умолчанию.

Примеры декларации простых объектов:

int i, j, k; char r; double gfd;

Рассмотрим основные базовые типы данных более подробно.

Наши рекомендации