Скачиваний:
2
Добавлен:
03.01.2024
Размер:
1.53 Mб
Скачать

СПбГУТ им. проф. М.А. Бонч-Бруевича Кафедра программной инженерии и вычислительной техники (ПИ и ВТ)

ПРОГРАММИРОВАНИЕ

Единственный способ изучать новый язык программирования - писать на нем программы.

Брайэн Керниган

Лекция 3: Язык Си. Начальные сведения

1.Общая характеристика языка Си.

Структура программы, написанной на языке СИ.

2.Директивы препроцессора.

3.Понятие о функции. Простейшие средства ввода-вывода.

4.Примеры простейших программ, написанных на языке Си (по ходу лекции).

Санкт-Петербург, 2023г.

1. Общая характеристика языка Си

Почему Си?

Один из наиболее популярных языков программирования

Синтаксис языка Си является основой для многих других языков программирования (С++, Java, JavaScript, С# и пр.)

Программы на Си хорошо переносимы между различными платформами (компиляторы Си существуют, практически, для всех типов процессоров)

Сочетает в себе черты языков низкого и высокого уровней

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

Адекватной замены этому языку нет и не предвидится, есть такие классы задач, для которых просто нет других подходящих языков; придётся, как следствие, «терпеть» Си таким, каков он есть.

Принять этот язык как феномен вам поможет понимание того, откуда он взялся, почему он именно таков, почему, несмотря на все свои «выверты» и «выкрутасы», этот язык продолжает удерживать первое место по популярности и почему, наконец, программиста, не знающего Си, всегда и везде будут воспринимать как сотрудника второго сорта, даже если писать на Си от него не требуется.

2

Рейтинг TIOBE Index

Рейтинг TIOBE Index

построен на оценке результатов поисковых запросов, содержащих название языка. Логика этого индекса очень проста:

«Если язык ищут в поисковых системах, то он популярен».

Интересно то, что C++ ни разу не смог превысить по популярности C.

www.tiobe.com/tiobeindex

3

Рейтинг IEEE Spectrum

Ежегодный рейтинг IEEE Spectrum Top Programming Language

использует 11 метрик из 8-ми источников, включая поисковые запросы, упоминания в твитере и даже упоминания в вакансиях на работу программиста.

Содной стороны этот рейтинг использует больше данных, но

сдругой стороны во многих источниках данные имеют связанный характер.

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

То есть у новых языков больше шансов попасть на вершину рейтинга.

Важностью особенностью рейтинга IEEE является то, что рейтинг интерактивный и можно поиграть с параметрами. В этом рейтинге лидирует Python.

https://spectrum.ieee.org/static/interactive-the-top- programming-languages-2020

4

Рейтинг Stack Overflow

Сайт Stack Overflow — это площадка, на которой разработчики могут задавать и отвечать на вопросы по программированию. Этот сайт имеет около 40 миллионов посещений в месяц. Есть русскоязычная версия сайта: ru.stackoverflow.com

Этот рейтинг рассчитывается на основе опроса разработчиков. В 2020 году было опрошено более 65 000 разработчиков и составлен рейтинг языков программирования. Скорее это рейтинг языков, которые вызывают вопросы. В этом рейтинге лидером стал JavaScript.

https://insights.stackoverflow.com/survey/2020

Такая популярность вполне объяснима, сейчас JavaScript бурно развивается и каждая новая возможность вызывает массу вопросов, поэтому программисты идут на сайт Stack Overflow, чтобы задать вопросы.

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

5

Общая характеристика языка Си

Из всей истории языка Си выделяются три основных фактора, позволяющих понять Си как явление:

во-первых, язык был создан в качестве заменителя языка ассемблера ;

во-вторых, одним из важнейших соображений при его создании была простота реализации;

в-третьих, язык был, что называется, «слеплен» под конкретную задачу, вставшую здесь и сейчас, и делали его,

как говорят в таких случаях, «на коленке».

Вряд ли Дэннис Ритчи, в то время ещё очень молодой, мог предполагать, что создаваемый им язык переживёт своего создателя и, уже просуществовав больше сорока лет (а описываемые события происходили в начале 1970-х годов), всё ещё не будет выказывать никаких признаков надвигающейся старости; сейчас можно достаточно смело предсказывать, что ещё по меньшей мере полтора-два десятка лет языку Си ничего не грозит, даже если вдруг кому-то удастся создать ему полноценную замену.

С технологической точки зрения ситуация сейчас выглядит так. Имеются по меньшей мере две области задач, где единственной альтернативой Си оказывается язык ассемблера:

это, во-первых, ядра операционных систем;

и, во-вторых, прошивки для микроконтроллеров — специализированных компьютеров, используемых для управления техникой (лифтами, стиральными машинами и т. п.); даже билет на метро представляет собой не что иное, как компьютер на основе микроконтроллера.

К вопросу о том, почему это так и чем здесь не устраивают другие языки, мы вернёмся позже, пока просто отметим, что работа на языке ассемблера оказывается в десятки раз более трудоёмкой, причём если когда-то давно ещё можно было ссылаться на более высокую эффективность ассемблерных программ, то сейчас оптимизаторы кода, встроенные прямо в компилятор, добиваются таких результатов по быстродействию, что человек, работая вручную, в большинстве случаев просто не может сделать лучше.

Поэтому, когда дело доходит до низкоуровневого

программирования, язык ассемблера используется лишь для тех редких и незначительных по объёму фрагментов, которые не могут быть сделаны даже на Си ; примером такого фрагмента может служить точка входа в обработчик прерывания в ядре ОС или, например, обращение к портам ввода-вывода в драйвере, и это обычно несколько строчек.

Большую часть низкоуровневой программы пишут именно на Си, что позволяет экономить дорогостоящее время программистов.

Разработка велась на микроЭВМ

DEC PDP-11:

Оперативная память – 24Кб

Из них используется ОС – 12 Кб

Задачи:

Разработка нового языка программирования

Разработка на нем операционной системы

6

Структура программы на языке Си

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

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

<определение типов пользователя - typedef> <описание прототипов функций> <определение глобальных переменных>

<функции>

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

Назначение функции main() – управление работой всей программы.

Функции main(), как правило, не имеет параметров и не возвращает результат (наличие круглых скобок обязательно).

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

С некоторой натяжкой можно считать, что функцию main() вызывает операционная система при старте программы.

Структура простой программы

#include <stdio.h> //содержит стандартные

//функции файлового ввода-вывода void main()

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

рrintf ("Это работает функция main! "); return 0; } //Окончание функции main

#include <stdio.h> int main (void)

{

printf ("Hello, World!\n"); return 0;

}

Строчка printf("Hello, world\n");

представляет собой вызов библиотечной функции, которая называется printf.

Отметим один крайне важный идеологический момент.

В отличие от Паскаля, где операторы ввода-вывода являются частью языка, в язык Си как таковой никакие средства ввода-вывода не входят.

Функция printf не является частью языка Си по меньшей мере в том смысле, что компилятор о ней ничего не знает .

Более того, сама функция printf написана на Си.

Мы использовали функцию printf, чтобы напечатать строку, но её возможности гораздо шире: она умеет печатать значения всех встроенных типов языка Си, причём целые числа можно печатать в разных системах счисления, можно управлять количеством печатаемых знаков и т. п.

Буква f в названии функции происходит от слова formatted, то есть эта функция осуществляет форматированный вывод.

Основные возможности printf мы рассмотрим на других занятиях. Отметим ещё один момент.

Функция printf — это действительно функция; она возвращает целое число, равное количеству напечатанных символов, то есть мы могли бы, например, написать:

x = printf("Hello, world\n");

7

Структура программы на языке Си

Отдельного рассмотрения заслуживает выражение

"Hello, world\n"

которое представляет собой строковую константу или,

как часто говорят, строковый литерал.

Следует обратить внимание на двойные кавычки; апострофы в Си тоже используются, но для других целей. Кроме того, внимание привлекает конструкция \n;

это обозначение символа перевода строки, то есть символа с кодом 10.

Можно вспомнить, что в Паскале мы в подобной ситуации применяли оператор writeln / write:

writeln(’Hello, world’); write(’Hello, world’#10);

то есть заставляли нашу программу сначала напечатать

данную строку, а затем перевести строку на печати, то есть фактически напечатать ещё и символ перевода строки.

Ввышеприведённом примере мы просто включили этот символ в состав печатаемой строки.

Обратим внимание на символ точки с запятой.

Впринципе, роль этого символа в языке Си подобна паскалевской, но есть одно важное отличие:

Если в Паскале точка с запятой разделяла операторы, то в Си точка с запятой является частью синтаксиса оператора.

#include <stdio.h> int main (void)

{

printf ("Hello, World!\n"); return 0;

}

Рассмотрим теперь следующую строку, «return 0;». Слово return в переводе с английского означает

«возврат»; в языке Си это оператор возврата из функции. Он делает две вещи:

во-первых, работа функции на этом заканчивается, что можно, например, использовать для досрочного её завершения (подобно паскалевскому exit);

во-вторых, его параметр — выражение, написанное после слова return, в данном случае 0 — задаёт то значение, которое вернёт функция (вспомним, что наша функция main описана как возвращающая целое число).

Вданном случае наша функция main вернёт число 0.

Значение, возвращаемое из main, предназначается ОС, а 0 в данном случае означает, что всё в порядке, т. е. программа, завершаясь, считает, что возложенную на неё миссию успешно выполнила.

8

 

 

Структура программы на языке Си

 

 

 

 

#include <stdio.h>

 

 

 

 

 

 

Нам осталось рассмотреть, пожалуй, самую

 

int main (void)

 

 

{

 

заковыристую строку в программе:

 

 

 

printf ("Hello, World!\n");

 

директиву

#include <stdio.h>

 

 

 

 

 

return 0;

 

Как уже, несомненно, догадались, эта директива в

 

}

 

тексте программы заменяет сама себя на полное

Важно понимать, что в этом файле содержится только

содержимое файла stdio.h, а нужно это, чтобы

заголовок функции printf, а самой функции там нет;

компилятор узнал про функцию printf — как уже

отсюда используемый суффикс «.h», от слова header, то

говорилось, сам по себе он о ней не знает.

есть «заголовок» — в английской терминологии это

Здесь следует отметить сразу несколько интересных

называется header file, а по-русски — «заголовочный

моментов:

файл».

 

 

Обращают на себя внимание используемые угловые

Всё, что компилятор узнает, увидев заголовок — это что

скобки <>, которые означают, что включаемый файл

где-то (и притом совершенно неважно, где) есть функция

следует искать в системных директориях;

с таким-то именем, принимающая столько-то параметров

точнее говоря, считается, что именно так следует

таких-то типов; как функция выглядит, что она делает —

включать любой файл, который не является сам по себе

этого компилятору знать не нужно.

частью нашей программы;

Дело в том, что компилятор генерирует не готовый

когда же мы пишем программу, состоящую из многих

машинный код, а объектный модуль, в котором пока что

файлов, то для включения своих собственных файлов

не хватает некоторых адресов; в данном случае

мы используем #include с параметром в двойных

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

кавычках “ “, например:

содержащий самой функции printf.

 

#include "mymodule.h"

Вместо неё модуль содержит указание на то, что

файл stdio.h — это вполне реальный файл; скорее всего,

редактору связей (линкеру) следует откуда-то добыть

функцию с таким именем, а её адрес подставить куда

он находится в вашей системе в директории

следует.

 

 

/usr/include, так что вы можете просмотреть его,

 

 

Иначе говоря, реальная функция printf появится в нашей

например, командой less:

программе только на этапе окончательной сборки, когда

 

less /usr/include/stdio.h

 

работа компилятора будет завершена.

9

Компиляция и интерпретация

Технология компиляции

Текст

 

 

 

 

 

 

 

 

Текстовый

 

Файл

 

Препро-

 

Файл

 

программы

 

(ИТ)

 

 

(ИМ)

 

редактор

 

 

цессор

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Транслятор

 

 

 

 

 

 

 

 

 

 

 

Файл

 

Линкер

 

Файл

 

Загрузчик

 

(компиля-

 

(ОМ)

 

(компонов-

 

(ИМ)

 

 

 

тор)

 

 

щик)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Файл

 

 

 

 

 

 

 

 

 

 

(ОМ)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Исходные

Исполняемая

Результаты

данные

программа

 

 

 

 

 

 

 

Программу на интерпретируемом языке

непосредственно выполняет без предварительного перевода программа-интерпретатор.

ЯВУ не зависит от внутренних машинных языков целевых процессоров, поэтому программы, написанные на языках высокого уровня, требуют перевода в машинные коды с помощью специальных программ –

трансляторов (компиляторов или

интерпретаторов), т.е. языки программирования могут быть реализованы как компилируемые и интерпретируемые.

Программа на компилируемом языке при помощи компилятора преобразуется (компилируется) в набор инструкций для данного типа процессора (машинный код – двоичные коды инструкций конкретного процессора), который далее преобразуется

(компонуется) в исполнимый модуль.

Технология интерпретации

Текст

программы

Транслятор Результаты

(интерпретатор)

Исходные

данные

10

Соседние файлы в папке Лекции