Язык программирования си. Язык программирования C (Си) Программирование на c

Язык программирования C (надо произносить «си») можно охарактеризовать как универсальный, экономичный, с полноценным набором операторов, с современной и потоком управления. Этот язык нельзя назвать «большим» языком, также он не претендует на звание «языка высокого уровня», он не создавался под какие-то конкретные задачи, напротив, его старались сделать максимально эффективным для любых применений. Этот интересный сплав идей, вложенных в язык программирования C сделал его очень удобным и более эффективным для широкого круга проблем, чем другие, возможно, даже более продвинутые языки.

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

C - язык программирования низкого уровня, но не стоит считать, что это плохо, на самом деле он просто оперирует теми же объектами, с которыми постоянно работают любые ЭВМ, с символами, адресами и числами. При этом все объекты объединяются, сравниваются или вычитаются с помощью обычных логических и арифметических действий, привычных для ЭВМ.

Хотя функции работы с составными объектами становятся нормой в мире кодинга и их встраивают во все современные языки программирования, C, в отличие от других, не умеет работать с такими объектами как строка, список, массив или множество. В нем нет никаких аналогов операций PL/1 над целыми строками и массивами.

С памятью С работает с помощью стека и статистического определения, других возможностей оперирования памятью С не имеет, вы не найдете в нем «кучу» (Heap) или «уборку мусора», как это умеют делать Паскаль или Алгол 68.

И даже самые базовые механизмы, ввода/вывода, язык С не обеспечивает, операторов Read и Write вы в нем не найдете, также отсутствуют и встроенные функции работы с файловой системой. Такие высокоуровневые операции обеспечиваются при помощи подключаемых библиотек.

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

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

С другой стороны, небольшое количество операторов сокращает время, требующееся для их заучивания, и вам хватит нескольких страниц, чтобы всех их описать. А еще как показывает практика, компилятор с «С» - это компактный инструмент, который достаточно прост в написании. Если пользоваться современными средствами, компилятор для совершенно новой ЭВМ будет готов всего за пару месяцев, при том, что на 80% его код будет аналогичен коду предыдущих версий. Благодаря такой своей особенности, язык программирования C считается очень мобильным. Да и эффективность его такова, что писать на ассемблере любые программы, которые критичные к производительности, как это было принято раньше, уже просто не имеет смысла. Самым лучшим примером тому является сама ОС «UNIX», которая на 90% написана на «С» и для нее, практически полностью создаваемое многочисленными программистами на этом же замечательном языке, который в данный момент считается в мире языком программирования номер один.

Изучение основ и тонкостей языка программирования C++. Учебник с практическими заданиями и тестами. Хотите научиться программировать? Тогда Вы по адресу - здесь бесплатное обучение программированию. Неважно, имеете ли Вы опыт или нет, эти уроки по программированию помогут Вам начать создавать, компилировать и отлаживать программы на языке C++ в разных средах разработки: Visual Studio, Code::Blocks, Xcode или Eclipse.

Множество примеров и подробных разъяснений. Отлично подойдут как для новичков (чайников), так и для более продвинутых. Объясняется всё с нуля и до самых деталей. Эти уроки (200+) дадут Вам хорошую базу/фундамент в понимании программирования не только на С++, но и в других языках программирования. И это абсолютно бесплатно!

Также рассматривается пошаговое создание игры на С++, графическая библиотека SFML и больше 50 задания для проверки своих навыков и знаний в C++. Дополнительным бонусом является .

За репост +20 к карме и моя благодарность!

Глава №0. Введение. Начало работы

Глава №1. Основы C++

Глава №2. Переменные и основные типы данных в C++

Глава №3. Операторы в C++

Глава №4. Область видимости и другие типы переменных в C++

Глава №5. Порядок выполнения кода в программе. Циклы, ветвления в C++

C - это достаточно "древний" язык программирования, он сформировался в начале 70-х. Не смотря на это, C - живой язык в том смысле, что он активно применяется в настоящее время. Он был придуман, использовался и используется для написания существенных частей программного кода Unix-подобных операционных систем. Также на нем пишут утилиты, компиляторы и реже прикладные программы. Поэтому C называют системным языком программирования.

Его живучесть можно объяснить тем, что принципы работы операционных систем относительно универсальны, они не подвержены тому прогрессу и разнообразию, которые можно наблюдать в среде десктопного и мобильного ПО, Web-приложений. C не является языком достаточно высокого уровня, он ближе к архитектуре компьютера. В результате программы на C получаются компактными и быстрыми.

C не поддерживает объектно-ориентированного программирования. Поддержка ООП реализована в C++. Хотя последний возник на основе языка C, он не является его "продолжением", а представляет собой отдельный язык, который можно изучать, не зная C. Однако изучение C полезно перед знакомством с его "продвинутым младшим братом", т.к. синтаксис языков похож, C не перегружает мозг начинающего программиста сверхвозможностями и приучает к пониманию сути происходящего.

Подходит ли C для первого знакомства с программированием? Если вы не обучаетесь в вузе по специальности, связанной с IT, то нет. C предполагает понимание организации и принципов работы аппаратного обеспечения, в частности – памяти. Здесь многое делается с помощью указателей, они играют ключевую роль; эта тема достаточно сложная для понимания и обычно не изучается в школе.

Конечно, с помощью C можно изучать основы программирования и не изучать при этом указатели. Однако человек будет думать, что знает C, мало зная о нем по существу. Язык C был создан разбирающимися в устройстве «железа» профессиональными программистами для написания операционной системы UNIX. Его не задумывали как язык для обучения начинающих.

Среды и компиляторы для программирования на C

Если вы пользуетесь одним из дистрибутивов GNU/Linux, вам подойдет любой текстовый редактор с подсветкой синтаксиса, также понадобятся GCC и терминал.

Существуют редакторы для программистов, включающие различные дополнения, в том числе терминал, просмотр каталогов и др. Например, Geany или Atom.

C – компилируемый язык программирования. В GNU/Linux для получения исполняемых файлов используется GCC – набор компиляторов, включающий в том числе компилятор для C. Чтобы из исходного файла (обычно таким файлам дают расширение *.с) получить исполняемый, надо выполнить в терминале команду примерно следующего вида:

gcc -o hello hello.c

Где gcc - команда, запускающая программу, выполняющую компиляцию и иные действия; -o – ключ, сообщающий, что мы вручную указываем имя исполняемого файла; hello – имя получаемого исполняемого файла; hello.c – имя файла с исходным кодом. Имя исполняемого файла можно не указывать:

gcc hello.c

В этом случае исполняемый файл будет иметь имя по умолчанию a.out.

Для Windows существует свой набор компиляторов – MinGW. Его можно использовать самостоятельно, однако он входит в состав простой среды разработки Dev-C++ , которая может оказаться хорошим выбором для обучения программированию на языках C и С++.

При сохранении выбирайте тип файла "C source files (*.c)". Компиляция и запуск программы выполняется при нажатии клавиши F9. После исполнения программа сразу закрывается и результат невозможно увидеть. Чтобы этого не происходило, прописывают две дополнительные строки: #include и getch(). (Возможно это не актуально для более новой версии Dev-C++.)

"Hello World" в GNU/Linux:

#include \n " ) ; }

"Hello World" в Windows:

#include #include int main () { printf ("Hello World\n " ) ; getch () ; }

С другой стороны, существует большое количество кроссплатформенных сред разработки. Например, Eclipse + модуль CDT, KDevelop, CLion. Последняя платна, выпускается компанией JetBrains – лидером в разработке IDE, однако имеет 30-ти дневный триальный период, чего может быть достаточно для обучения. CLion удобнее других IDE.

"Hello World" на C

На примере простейшей программы сразу отметим некоторые особенности языка программирования C.

В языке C роль основной ветки программы берет на себя функция main(). Эта функция всегда должна присутствовать в законченной программе на языке C, и исполнение программы начинается именно с нее. Однако объявленные внутри нее переменные не являются глобальными, их область видимости простирается только на main(). Тем не менее в языке программирования C почти весь программный код заключается в функции, и функция main() является главной и обязательной.

По умолчанию функция main() возвращает тип данных int, поэтому можно не указывать тип возвращаемых данных. Однако компилятор в этом случае выносит предупреждение.

Функция printf() предназначена для вывода данных. Ее назначение аналогично процедуре write() языка Pascal и функции print() в Python. Функция printf() после вывода не выполняет переход на новую строку. Поэтому для перехода используется специальный символ, который обозначается комбинацией \n. Законченные выражения на языке C разделяются точкой с запятой.

В языке C функции ввода-вывода не являются частью языка. Например, в Python нам не надо импортировать никакой модуль, чтобы пользоваться функциями print() и input(). В C же мы не можем просто вызвать функцию printf(), т.к. в самом C ее просто нет. Эту функцию, а также ряд других, можно подключить с помощью заголовочного файла stdio.h. Именно для этого в начале программы прописана строка #include . Include с английского переводится как "включить", а stdio есть сокращение от "стандартный ввод-вывод (input-output)".

В заголовочных файлах (они оканчиваются на *.h) обычно содержаться объявления тех или иных функций. Объявление - это просто описание функции: какие параметры она принимает и что возвращает. Сам код функции (определение) находится не в заголовочном файле, а в библиотеках (других файлах), которые могут быть уже скомпилированы и расположены в системных каталогах. Перед компиляцией программы запускается препроцессор языка C. Помимо прочего он включает в начало файла программы содержимое указанных в ней заголовочных файлов.

Практическая работа

Закомментируйте 1 первую строчку кода программы HelloWorld. Попробуйте скомпилировать программу. Удалось ли получить исполняемый файл? Какое предупреждение выдал компилятор?

1 // - однострочный комментарий на языке C; /* … */ - многострочный комментарий на языке C.

Особенности

Обзор

Язык программирования Си отличается минимализмом. Авторы языка хотели, чтобы программы на нём легко компилировались с помощью однопроходного компилятора , после компиляции каждой элементарной составляющей программы соответствовало весьма небольшое число машинных команд, а использование базовых элементов языка не задействовало библиотеку времени выполнения. Однопроходный компилятор компилирует программу, не возвращаясь назад, к уже откомпилированному тексту. Поэтому использованию функции должно предшествовать её объявление. Код на Си можно легко писать на низком уровне абстракции, почти как на ассемблере . Иногда Си называют «универсальным ассемблером» или «ассемблером высокого уровня», что отражает различие языков ассемблера для разных платформ и единство стандарта Си, код которого может быть скомпилирован без изменений практически на любой модели компьютера . Си часто называют языком среднего уровня или даже низкого уровня , учитывая то, как близко он работает к реальным устройствам.

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

Программа «Hello, World!»

Эта простая программа, появившаяся в первом издании книги «Язык программирования Си » Кернигана и Ритчи, обычно является первой программой большинства учебников Си. Она печатает сообщение «Hello World!» на стандартном устройстве вывода (которым, как правило, является монитор (дисплей) , но может быть и файл , какое-либо устройство или область в памяти, в зависимости от того, как отражается стандартное устройство вывода на данной платформе).

Main() { printf ("Hello, World!\n " ) ; }

Несмотря на то, что на большинстве современных компиляторов эта программа может быть корректно скомпилирована, она порождает несколько предупреждений на компиляторах стандарта ANSI C . Кроме того, этот код не будет компилироваться, если компилятор жёстко следует стандарту

#include int main(void ) { printf ("Hello, World!\n " ) ; return 0 ; }

В первой строке программы расположена директива препроцессора #include , встретив которую, компилятор заменяет её на полный текст файла, на который она ссылается. В данном случае эта строка будет заменена стандартным заголовочным файлом

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

Фигурные скобки после функции main обозначают её определение. Слово int говорит, что функция main возвращает (вычисляет) целое число . Слово void показывает, что функция main не требует от вызывающего ни параметров, ни аргументов.

Следующая строка «вызывает» или исполняет функцию stdio.h содержит информацию, описывающую то, как нужно вызывать эту функцию. В данном примере этой функции передаётся единственный аргумент, содержащий текстовую строку «Hello, World!\n» . Последовательность \n транслируется в символ «новая строка», который при отображении соответственно обозначает разрыв строки. Функция printf возвращает значение типа int , которое в этом примере полностью отбрасывается.

Выражение return заставляет программу прекратить выполнение данной функции (main в этом случае), возвращая вызвавшей функции значение, указанное после ключевого слова return (0 в этом случае). Так как текущая функция - это main , то вызывающим является то, что запустило программу. Последняя фигурная скобка обозначает конец определения функции main .

Комментарии

Текст, заключённый в служебные символы /* и */ в этом порядке, полностью игнорируется компилятором. Компиляторы, совместимые со стандартом C99, также позволяют использовать комментарии, начинающиеся с символов // и заканчивающиеся переводом строки

Типы

Хранение данных

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

В Си есть три разных способа выделения памяти для объектов:

  • Статическое выделение памяти : пространство для объектов создаётся в области хранения данных кода программы в момент компиляции; время жизни таких объектов совпадает со временем жизни этого кода.
  • Автоматическое выделение памяти : объекты можно временно хранить в стеке ; эта память затем автоматически освобождается и может быть использована снова, после того, как программа выходит из блока, использующего её.
  • Динамическое выделение памяти : блоки памяти нужного размера могут запрашиваться во время выполнения программы с помощью библиотечных функций malloc , realloc и free из области памяти, называемой кучей . Эти блоки освобождаются и могут быть использованы снова после вызова для них функции free .

Все три этих способа хранения данных пригодны в различных ситуациях и имеют свои преимущества и недостатки. Например, статическое выделение памяти не имеет накладных расходов по выделению, автоматическое выделение - лишь малые расходы при выделении, а вот динамическое выделение потенциально требует больших расходов и на выделение, и на освобождение памяти. С другой стороны, память стека гораздо больше ограничена, чем статическая, или память в куче. Только динамическая память может использоваться в случаях, когда размер используемых объектов заранее неизвестен. Большинство программ на Си интенсивно используют все три этих способа.

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

Набор используемых символов

Язык Си был создан уже после внедрения стандарта Фортран , Лисп и Кобол использовали только круглые скобки () , а в Си есть и круглые () , и квадратные , и фигурные { } . Кроме того, в Си различаются заглавные и строчные буквы, а более старые языки использовали только заглавные.

Проблемы

Многие элементы Си потенциально опасны, а последствия неправильного использования этих элементов зачастую непредсказуемы. Керниган говорит: «Си - инструмент, острый, как бритва : с его помощью можно создать и элегантную программу, и кровавое месиво ». В связи со сравнительно низким уровнем языка многие случаи неправильного использования опасных элементов не обнаруживаются и не могут быть обнаружены ни при компиляции, ни во время исполнения. Это часто приводит к непредсказуемому поведению программы. Иногда в результате неграмотного использования элементов языка появляются уязвимости в системе безопасности . Необходимо заметить, что использования многих таких элементов можно избежать.

Чаще всего источником ошибки является обращение к несуществующему элементу массива . Несмотря на то, что Си непосредственно поддерживает статические массивы, он не имеет средств проверки индексов массивов (проверки границ). Например, возможна запись в шестой элемент массива из пяти элементов, что, естественно, приведёт к непредсказуемым результатам. Частный случай такой ошибки называется ошибкой переполнения буфера . Ошибки такого рода приводят к большинству проблем с безопасностью.

Другим потенциальным источником опасных ситуаций служит механизм указателей . Указатель может ссылаться на любой объект в памяти, включая и исполняемый код программы, и неправильное использование указателей может порождать непредсказуемые эффекты и приводить к катастрофичным последствиям. К примеру, указатель может быть неинициализированным или, в результате неверных арифметических операций над указателем, указывать в произвольное место памяти; на некоторых платформах работа с таким указателем может вызвать аппаратный останов программы, на незащищённых же платформах это может привести к порче произвольных данных в памяти, причём эта порча может проявиться в самые произвольные моменты времени и намного позже момента порчи. Также, область динамической памяти, на которую ссылается указатель, может быть освобождена (и даже выделена после этого под другой объект) - такие указатели называются «висячими». Или, наоборот, после манипуляций с указателями на область динамической памяти может не остаться ссылок, и тогда эта область, называемая «мусором» (garbage), никогда не будет освобождена, что может приводить к «утечкам памяти» в программе. В других языках подобные проблемы пытаются решить введением более ограниченных ссылочных типов.

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

Ещё одной распространённой проблемой является то, что память не может быть использована снова, пока она не будет освобождена программистом с помощью функции free() . В результате программист может случайно забыть освобождать эту память, но продолжать её выделять, занимая всё большее и большее пространство. Это обозначается термином утечка памяти . Наоборот, возможно освободить память слишком рано, но продолжать её использовать. Из-за того, что система выделения может использовать освобождённую память по-другому, это ведёт к непредсказуемым последствиям. Эти проблемы решаются в языках со сборкой мусора . С другой стороны, если память выделяется в функции и должна освобождаться после выхода из функции, данная проблема решается с помощью автоматического вызова деструкторов в языке C++, или с помощью локальных массивов, используя расширения С99.

Функции с переменным количеством аргументов также являются потенциальным источником проблем. В отличие от обычных функций, имеющих прототип , стандартом не регламентируется проверка функций с переменным числом аргументов. Если передаётся неправильный тип данных, то возникает непредсказуемый, если не фатальный результат. Например, семейство функций printf стандартной библиотеки языка Си, используемое для генерации форматированного текста для вывода, хорошо известно за его потенциально опасный интерфейс с переменным числом аргументов, которые описываются строкой формата. Проверка типов в функциях с переменным числом аргументов является задачей каждой конкретной реализации такой функции, однако многие современные компиляторы в частности проверяют типы в каждом вызове printf , генерируя предупреждения в случаях, когда список аргументов не соответствует строке формата. Следует заметить, что невозможно статически проконтролировать даже все вызовы функции printf , поскольку строка формата может создаваться в программе динамически, поэтому как правило никаких проверок других функций с переменным числом аргументов компилятором не производится.

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

История

Ранние разработки

Язык программирования Си был разработан в лабораториях Bell Labs в период с по 1973 годы . Согласно Ритчи , самый активный период творчества пришёлся на 1972 год . Язык назвали «Си» (C - третья буква латинского алфавита), потому что многие его особенности берут начало от старого языка «Би» (B - вторая буква латинского алфавита). Существует несколько различных версий происхождения названия языка Би. Кен Томпсон указывает на язык программирования

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

  • некоторые компиляторы не придерживаются по умолчанию стандарта ANSI C, или его преемника; или
  • они рассчитаны на определённое значение размера некоторых типов данных или на определённый способ хранения этих данных в памяти для конкретной платформы.
  • C99

    Основная статья : 1995 году в стандарт Си была внесена Первая нормативная поправка, но её почти никто не признавал). Однако в конце 1990-х годов стандарт подвергся пересмотру, что привело к публикации ISO 9899:1999 в 1999 году . Этот стандарт обычно называют «С99». В марте 2000 года он был принят и адаптирован ANSI.

    Вот некоторые новые особенности С99:

    • подставляемые функции (inline);
    • отсутствие ограничений на объявление локальных переменных (как и в С++);
    • новые типы данных, такие как long long int (для облегчения перехода от 32- к 64-битным числам), явный булевый тип данных и тип complex для представления комплексных чисел;
    • массивы переменной длины;
    • поддержка ограниченных указателей (restrict);
    • именованная инициализация структур: struct { int x, y, z; } point = { .y=10, .z=20, .x=30 };
    • поддержка однострочных комментариев, начинающихся на // , заимствованных из C++ (многие компиляторы Си поддерживали их и ранее в качестве дополнения);
    • несколько новых библиотечных функций, таких как snprintf ;
    • несколько новых заголовочных файлов , таких как stdint.h .

    Интерес к поддержке новых особенностей С99 в настоящее время смешан. В то время как GCC , компилятор Си от Sun Microsystems и некоторые другие компиляторы в настоящее время поддерживают большую часть новых особенностей С99, компиляторы компаний Microsoft не делают этого, причём похоже, что две эти компании и не думают их добавлять.

    Связь с C++

    Приоритет операций в Си

    Ниже приведены операции в порядке убывания приоритета. Операции, приведённые на одной строчке, имеют одинаковый приоритет. Операции, помеченные как R->L, имеют правую ассоциативность (то есть при сочетании равноприоритетных операций без скобок они вычисляются справа налево; при этом порядок вычисления аргументов большинства операций не специфицирован и зависит от реализаций):

    Постфиксные операции () . -> ++ --
    Унарные операции (R->L) ++ -- & * + - ~ ! sizeof (type)
    Мультипликативные * / %
    Аддитивные + -
    Сдвиговые << >>
    Операции сравнение < > <= >=
    Операции проверки равенство == !=
    Побитовые & ^ |
    Логические && ||
    Условная операция (R->L) ?:
    Операции присваивания (R->L) = *= /= %= += -= <<= >>= &= ^= |=
    Последовательное вычисление ,

    Известные компиляторы языка Си

    • Open Watcom

    Компиляторы на динамические языки и платформы

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

    Следующие проекты предназначены для этих целей:

    • Alchemy - компилятор из Си/C++ в Flash- и Adobe AIR -приложениях.
    • AMPC -- компилятор из Си в виртуальную машину

      Примечания

      См. также

      • Cyclone (язык программирования) - безопасный диалект языка Си
      • Категория:Компиляторы C

      Ссылки

      • ISO/IEC JTC1/SC22/WG14 official home (англ.) . - Официальная страница международной рабочей группы по стандартизации языка программирования Си. Проверено 20 февраля 2009.