Язык программирования Си разрабатывался в период с 1969 по 1973 годы в лабораториях Bell Labs, и к 1973 году на него была переписана большая часть ядраUNIX, первоначально написанного на ассемблере PDP-11/20. Название языка стало логическим продолжением старого языка «Би»[a], многие особенности которого были положены в основу.
По мере развития язык сначала стандартизировали как ANSI C, а затем этот стандарт был принят комитетом по международной стандартизации ISO как ISO C, ставший также известным под названием C90. В стандарте С99 язык получил новые возможности, такие как массивы переменной длины и встраиваемые функции. А в стандарте C11 в язык добавили реализацию потоков и поддержку атомарных типов. Однако с тех пор язык развивается медленно, и в стандарт С18 попали лишь исправления ошибок стандарта C11.
Язык Си разрабатывался как язык системного программирования, для которого можно создать однопроходный компилятор. Стандартная библиотека также невелика. Как следствие данных факторов — компиляторы разрабатываются сравнительно легко[2]. Поэтому данный язык доступен на самых различных платформах. К тому же, несмотря на свою низкоуровневую природу, язык ориентирован на переносимость. Программы, соответствующие стандарту языка, могут компилироваться под различные архитектуры компьютеров.
Целью языка было облегчение написания больших программ с минимизацией ошибок по сравнению с ассемблером, следуя принципам процедурного программирования, но избегая всего, что может привести к дополнительным накладным расходам, специфичным для языков высокого уровня.
Основные особенности Си:
простая языковая база, из которой в стандартную библиотеку вынесены многие существенные возможности, вроде математических функций или функций работы с файлами;
Часть отсутствующих возможностей может имитироваться встроенными средствами (например, сопрограммы можно имитировать с помощью функций setjmp и longjmp), часть добавляется с помощью сторонних библиотек (например, для поддержки многозадачности и для сетевых функций можно использовать библиотеки pthreads, sockets и тому подобные; существуют библиотеки для поддержки автоматической сборки мусора[3]), часть реализуется в некоторых компиляторах в виде расширений языка (например, вложенные функции в GCC). Существует несколько громоздкая, но вполне работоспособная методика, позволяющая реализовывать на Си механизмы ООП[4], базирующаяся на фактической полиморфности указателей в Си и поддержке в этом языке указателей на функции. Механизмы ООП, основанные на данной модели, реализованы в библиотеке GLib и активно используются в фреймворке GTK+. GLib предоставляет базовый класс GObject, возможности наследования от одного класса[5] и реализации множества интерфейсов[6].
После появления язык был хорошо принят, потому что он позволял быстро создавать компиляторы для новых платформ, а также позволял программистам довольно точно представлять, как выполняются их программы. Благодаря близости к языкам низкого уровня программы на Си работали эффективнее написанных на многих других языках высокого уровня, и лишь оптимизированный вручную код на ассемблере мог работать ещё быстрее, потому что давал полный контроль над машиной. На сегодняшний день развитие компиляторов и усложнение процессоров привело к тому, что вручную написанный ассемблерный код (кроме разве что очень коротких программ) практически не выигрывает по сравнению с кодом, генерируемым компиляторами, при этом Си продолжает оставаться одним из наиболее эффективных языков высокого уровня.