С ( / ы я / , как и в письме с ) представляет собой универсальный , процедурный компьютерный язык программирования , поддерживающее структурированное программирование , объем лексического переменный , и рекурсию , с системой статического типа . По своей конструкции C предоставляет конструкции, которые эффективно отображаются на типичные машинные инструкции . Он нашел прочное применение в приложениях, ранее написанных на языке ассемблера . К таким приложениям относятся операционные системы и различное прикладное программное обеспечение.для компьютерных архитектур, от суперкомпьютеров до ПЛК и встроенных систем .
Парадигма | Императивная ( процессуальная ), структурированная |
---|---|
Разработано | Деннис Ричи |
Разработчик | Деннис Ричи и Bell Labs (создатели); ANSI X3J11 ( ANSI C ); ISO / IEC JTC1 / SC22 / WG14 (ISO C) |
Впервые появился | 1972 [2] |
Стабильный выпуск | C17 / июнь 2018 г . |
Предварительный выпуск | |
Печатная дисциплина | Статический , слабый , явный , номинальный |
Операционные системы | Кроссплатформенность |
Расширения имени файла | .c, .h |
Веб-сайт | www www |
Основные реализации | |
K&R C , GCC , Clang , Intel C , C ++ Builder , Microsoft Visual C ++ , Watcom C | |
Диалекты | |
Циклон , унифицированный параллельный C , Split-C , Cilk , C * | |
Под влиянием | |
B ( BCPL , CPL ), АЛГОЛ 68 , [4] Сборка , PL / I , FORTRAN | |
Под влиянием | |
Многочисленные : AMPL , AWK , csh , C ++ , C-- , C # , Objective-C , D , Go , Java , JavaScript , Julia , Limbo , LPC , Perl , PHP , Pike , Processing , Python , Rust , Seed7 , Vala , Verilog (HDL), [5] Ним , Зиг | |
|
Преемник языка программирования B , C первоначально была разработана в Bell Labs по Деннис Ритчи в период с 1972 по 1973 год построить утилиты , работающие на Unix . Он был применен для повторной реализации ядра операционной системы Unix. [6] В течение 1980-х годов C постепенно завоевал популярность. Он стал одним из наиболее широко используемых языков программирования , [7] [8] с C компиляторов от различных производителей , доступных для большинства существующих компьютерных архитектур и операционных систем. C стандартизирован ANSI с 1989 года ( ANSI C ) и Международной организацией по стандартизации (ISO).
C - императивный процедурный язык. Он был разработан для компиляции, чтобы обеспечить низкоуровневый доступ к памяти и языковым конструкциям, которые эффективно отображаются на машинные инструкции , и все это с минимальной поддержкой времени выполнения . Несмотря на свои низкоуровневые возможности, язык был разработан для поощрения кроссплатформенного программирования. Соответствующая стандартам программа на языке C, написанная с учетом переносимости, может быть скомпилирована для широкого спектра компьютерных платформ и операционных систем с небольшими изменениями в ее исходном коде. [ необходима цитата ]
По состоянию на январь 2021 [Обновить]года язык C занял первое место в индексе TIOBE , показателе популярности языков программирования, поднявшись с нуля. 2 место в прошлом году. [9]
Обзор
Как и большинство процедурных языков в традиции Алгола , C имеет средства для структурированного программирования и допускает область видимости лексических переменных и рекурсию. Его система статического типа предотвращает непреднамеренные операции. В C весь исполняемый код содержится в подпрограммах (также называемых «функциями», хотя и не строго в смысле функционального программирования ). Параметры функции всегда передаются по значению (кроме массивов ). Передача по ссылке моделируется в C путем явной передачи значений указателя . Исходный текст программы на C имеет свободный формат , с точкой с запятой в качестве признака конца оператора и фигурными скобками для группировки блоков операторов .
Язык C также обладает следующими характеристиками:
- Язык имеет небольшое, фиксированное количество ключевых слов, в то числе полного набора потоков управления примитивами:
if/else
,for
,do/while
,while
, иswitch
. Пользовательские имена не отличаются от ключевых слов никакими сигилами . - Он имеет большое количество арифметических, побитовые, и логические операторы:
+
,+=
,++
,&
,||
и т.д. - В одном операторе может быть выполнено более одного присваивания .
- Функции:
- Если в этом нет необходимости, возвращаемые функции можно игнорировать.
- Указатели на функции и данные допускают произвольный полиморфизм во время выполнения .
- Функции не могут быть определены в лексической области других функций.
- Типизация данных статична , но не соблюдается ; все данные имеют тип, но возможны неявные преобразования .
- Декларации не синтаксис контекст использования подражает. В C нет ключевого слова "define"; вместо этого заявление, начинающееся с имени типа, считается объявлением. Ключевого слова "функция" нет; вместо этого функция обозначается наличием списка аргументов в скобках.
- Возможны определяемые пользователем ( typedef ) и составные типы.
- Гетерогенные агрегированные типы данных (
struct
) позволяют получить доступ к связанным элементам данных и назначить их как единое целое. - Союз - это структура с перекрывающимися членами; действителен только последний сохраненный член.
- Индексация массивов - это вторичная нотация, определенная в терминах арифметики указателей. В отличие от структур, массивы не являются объектами первого класса: их нельзя назначать или сравнивать с помощью отдельных встроенных операторов. Ключевое слово "массив" не используется или не определяется; вместо этого квадратные скобки обозначают массивы, например, синтаксически
month[11]
. - Перечислимые типы возможны с
enum
ключевым словом. Они свободно конвертируются с целыми числами. - Строки не являются отдельным типом данных, но обычно реализуются как массивы символов с завершающим нулем .
- Гетерогенные агрегированные типы данных (
- Низкоуровневый доступ к памяти компьютера возможен путем преобразования машинных адресов в типизированные указатели .
- Процедуры (подпрограммы, не возвращающие значения) - это особый случай функции с нетипизированным возвращаемым типом
void
. - Препроцессор выполняет макрос определения, исходный код включение файла и условную компиляцию .
- Существует базовая форма модульности : файлы могут быть скомпилированы отдельно и связаны друг с другом, с контролем над которым функцией и данные объекты являются видимыми для других файлов с помощью staticи
extern
атрибутами. - Сложные функции, такие как ввод-вывод , манипуляции со строками и математические функции, последовательно делегируются библиотечным подпрограммам .
Хотя C не включает некоторые функции, имеющиеся в других языках (например, ориентацию объектов и сборку мусора ), они могут быть реализованы или эмулированы, часто с использованием внешних библиотек (например, объектной системы GLib или сборщика мусора Boehm ).
Отношения к другим языкам
Многие более поздние языки прямо или косвенно заимствованы из C, включая C ++ , C # , оболочку C Unix , D , Go , Java , JavaScript (включая транспилеры ), Julia , Limbo , LPC , Objective-C , Perl , PHP , Python , Ruby , Rust , Swift , Verilog и SystemVerilog (языки описания оборудования). [5] Эти языки позаимствовали многие свои управляющие структуры и другие базовые функции из C. Большинство из них (Python является драматическим исключением) также выражают синтаксис, очень похожий на C, и они, как правило, сочетают узнаваемые выражения и синтаксис операторов C с базовыми системами типов, моделями данных и семантикой, которые могут радикально отличаться.
История
Ранние разработки
Год | Стандарт C [10] |
---|---|
1972 г. | Рождение |
1978 г. | K&R C |
1989/1990 | ANSI C и ISO C |
1999 г. | C99 |
2011 г. | C11 |
2017 г. | C17 |
TBD | C2x |
Происхождение C тесно связано с развитием операционной системы Unix , первоначально реализованной на языке ассемблера на PDP-7 Деннисом Ритчи и Кеном Томпсоном с использованием нескольких идей коллег. В конце концов, они решили перенести операционную систему на PDP-11 . Исходная версия Unix для PDP-11 также была разработана на языке ассемблера. [6]
Томпсон хотел использовать язык программирования для создания утилит для новой платформы. Сначала он пытался создать компилятор Фортрана , но вскоре отказался от этой идеи. Вместо этого он создал урезанную версию недавно разработанного языка системного программирования BCPL . Официальное описание BCPL не было доступно в то время, [11] и Томпсон изменил синтаксис , чтобы быть менее многословным, производя подобный , но несколько более простой B . [6] Однако в конечном итоге на B было написано несколько утилит, потому что он был слишком медленным, и B не мог воспользоваться такими функциями PDP-11, как байтовая адресация.
В 1972 году Ричи начал улучшать B, что привело к созданию нового языка C. [12] Компилятор C и некоторые утилиты, созданные с его помощью, были включены в версию 2 Unix . [13]
В версии 4 Unix , выпущенной в ноябре 1973 года, ядро Unix было широко повторно реализовано на C. [6] К этому времени язык C приобрел некоторые мощные функции, такие как типы.struct
Препроцессор был представлен примерно в 1973 году по настоянию Алана Снайдера, а также в знак признания полезности механизмов включения файлов, доступных в BCPL и PL / I. Его исходная версия содержала только включенные файлы и простую замену строк: #include
и #define
макросов без параметров. Вскоре после этого он был расширен, в основном Майком Леском, а затем Джоном Рейзером, для включения макросов с аргументами и условной компиляции. [14]
Unix была одним из первых ядер операционной системы, реализованных на языке, отличном от ассемблера . Более ранние экземпляры включают систему Multics (которая была написана на PL / I ) и Master Control Program (MCP) для Burroughs B5000 (которая была написана на ALGOL ) в 1961 году. Примерно в 1977 году Ричи и Стивен С. Джонсон внесли дальнейшие изменения в язык, облегчающий переносимость операционной системы Unix. Портативный компилятор Си Джонсона послужил основой для нескольких реализаций Си на новых платформах. [12]
K&R C
В 1978 году Брайан Керниган и Деннис Ритчи опубликовал первое издание Язык программирования C . [1] Эта книга, известная программистам на C как K&R , в течение многих лет служила неформальной спецификацией языка. Версия C, которую он описывает, обычно называется « K&R C ». Поскольку он был выпущен в 1978 году, он также упоминается как C78 . [15] Второе издание книги [16] охватывает более поздний стандарт ANSI C , описанный ниже.
K&R представила несколько языковых функций:
- Стандартная библиотека ввода-вывода
long int
тип данныхunsigned int
тип данных- Операторы составного присваивания формы (например, ) были изменены на форму (то есть ), чтобы устранить семантическую неоднозначность, созданную такими конструкциями, как , которые интерпретировались как (уменьшение на 10) вместо предполагаемого (пусть будет - 10).
=op
=-
op=
-=
i=-10
i =- 10
i
i = -10
i
Даже после публикации стандарта ANSI 1989 года, в течение многих лет K&R C все еще считался " наименьшим общим знаменателем ", которым программисты на C ограничивались, когда была желательна максимальная переносимость, поскольку многие старые компиляторы все еще использовались, и потому что тщательно написанные K&R Код C также может быть законным стандартом C.
В ранних версиях C только функции, возвращающие типы, отличные от того, int
должны быть объявлены, если они используются до определения функции; Предполагалось, что функции, используемые без предварительного объявления, возвращают тип int
.
Например:
long some_function (); / * int * / other_function ();/ * int * / call_function () { long test1 ; register / * int * / test2 ; test1 = some_function (); если ( test1 > 0 ) test2 = 0 ; иначе test2 = другая_функция (); return test2 ; }
В int
спецификаторах типа , которые закомментированы могут быть опущены в K & R C, но необходимы в более поздних стандартах.
Поскольку объявления функций K&R не включали никакой информации об аргументах функции, проверки типа параметра функции не выполнялись, хотя некоторые компиляторы выдают предупреждающее сообщение, если локальная функция вызывается с неправильным количеством аргументов или если несколько вызовов внешней функции использовали разное количество или типы аргументов. Были разработаны отдельные инструменты, такие как утилита lint для Unix, которые (помимо прочего) могли проверять согласованность использования функций в нескольких исходных файлах.
За годы, прошедшие после публикации K&R C, в язык были добавлены несколько функций, поддерживаемых компиляторами от AT&T (в частности, PCC [17] ) и некоторых других поставщиков. К ним относятся:
void
функции (т.е. функции без возвращаемого значения)- возвращаемые функции
struct
илиunion
типы (а не указатели) - Назначение для
struct
типов данных - перечислимые типы
Большое количество расширений и отсутствие согласия по стандартной библиотеке вместе с популярностью языка и тем фактом, что даже компиляторы Unix не реализовали точно спецификацию K&R, привели к необходимости стандартизации.
ANSI C и ISO C
В конце 1970-х и 1980-х годах версии C были реализованы для широкого спектра мэйнфреймов , мини-компьютеров и микрокомпьютеров , включая IBM PC , поскольку его популярность стала значительно расти.
В 1983 году Американский национальный институт стандартов (ANSI) сформировал комитет X3J11, чтобы установить стандартную спецификацию C. X3J11, основанную на стандарте C на реализации Unix; однако непереносимая часть библиотеки Unix C была передана рабочей группе 1003 IEEE, чтобы стать основой для стандарта POSIX 1988 года . В 1989 году стандарт C был ратифицирован как ANSI X3.159-1989 «Язык программирования C». Эту версию языка часто называют ANSI C , Standard C или иногда C89.
В 1990 году стандарт ANSI C (с изменениями форматирования) был принят Международной организацией по стандартизации (ISO) как ISO / IEC 9899: 1990, который иногда называют C90. Следовательно, термины «C89» и «C90» относятся к одному и тому же языку программирования.
ANSI, как и другие национальные органы по стандартизации, больше не разрабатывает стандарт C независимо, а полагается на международный стандарт C, поддерживаемый рабочей группой ISO / IEC JTC1 / SC22 / WG14. Национальное принятие обновления международного стандарта обычно происходит в течение года после публикации ISO.
Одной из целей процесса стандартизации C было создание расширенного набора K&R C, включающего многие из введенных впоследствии неофициальных функций. Комитет по стандартам также включил несколько дополнительных функций, таких как прототипы функций (заимствованные из C ++), void
указатели, поддержка международных наборов символов и локалей , а также усовершенствования препроцессора. Хотя синтаксис для объявлений параметров был расширен, чтобы включить стиль, используемый в C ++, интерфейс K&R по-прежнему разрешен для совместимости с существующим исходным кодом.
C89 поддерживается текущими компиляторами C, и на нем основан самый современный код C. Любая программа, написанная только на Стандартном C и без каких-либо предположений, зависящих от оборудования, будет корректно работать на любой платформе с соответствующей реализацией C в пределах ее ресурсов. Без таких мер предосторожности программы могут компилироваться только на определенной платформе или с определенным компилятором, например, из-за использования нестандартных библиотек, таких как библиотеки графического интерфейса , или из-за зависимости от атрибутов компилятора или платформы, таких как как точный размер типов данных и байтовый порядок байтов .
В случаях, когда код должен компилироваться либо стандартными компиляторами, либо компиляторами на основе K&R C, __STDC__
макрос может использоваться для разделения кода на разделы Standard и K&R, чтобы предотвратить использование в компиляторе на основе K&R C функций, доступных только в Standard. С.
После процесса стандартизации ANSI / ISO спецификация языка C оставалась относительно неизменной в течение нескольких лет. В 1995 году была опубликована Нормативная поправка 1 к стандарту C 1990 года (ISO / IEC 9899 / AMD1: 1995, неофициально известный как C95), чтобы исправить некоторые детали и добавить более широкую поддержку международных наборов символов. [18]
C99
Стандарт C был дополнительно пересмотрен в конце 1990-х, что привело к публикации ISO / IEC 9899: 1999 в 1999 году, который обычно называют « C99 ». С тех пор в него трижды вносились технические поправки. [19]
C99 представил несколько новых функций, в том числе встроенные функции , несколько новых типов данных (в том числе long long int
и complex
тип для представления комплексных чисел ), массивы переменной длины и гибкие элементы массива , улучшенную поддержку IEEE 754 с плавающей запятой, поддержку макросов с переменными числами (макросы переменных arity ) и поддержка однострочных комментариев, начинающихся с //
, как в BCPL или C ++. Многие из них уже были реализованы как расширения в нескольких компиляторах C.
C99 по большей части обратно совместим с C90, но в некоторых отношениях более строг; в частности, объявление, в котором отсутствует спецификатор типа, больше не int
подразумевается. Стандартный макрос __STDC_VERSION__
определяется со значением, 199901L
указывающим, что доступна поддержка C99. GCC , Solaris Studio и другие компиляторы C теперь поддерживают многие или все новые функции C99. Однако компилятор C в Microsoft Visual C ++ реализует стандарт C89 и те части C99, которые необходимы для совместимости с C ++ 11 . [20] [ требуется обновление ]
Кроме того, теперь требуется поддержка идентификаторов Unicode (имен переменных / функций) в форме экранированных символов (например \U0001f431
). Поддержка необработанных имен Unicode, например 🐱
, необязательна.
C11
В 2007 году началась работа над еще одной версией стандарта C, неофициально называемой «C1X», до его официальной публикации 8 декабря 2011 года. Комитет по стандартам C принял руководящие принципы, ограничивающие принятие новых функций, которые не были протестированы существующими реализациями.
Стандарт C11 добавляет множество новых функций в C и библиотеку, включая универсальные макросы типов, анонимные структуры, улучшенную поддержку Unicode, атомарные операции, многопоточность и функции с проверкой границ. Это также делает некоторые части существующей библиотеки C99 необязательными и улучшает совместимость с C ++. Стандартный макрос __STDC_VERSION__
определен как 201112L
указывающий на то, что доступна поддержка C11.
C17
Опубликованный в июне 2018 года, C17 является текущим стандартом для языка программирования C. Он не вводит никаких новых языковых функций, только технические исправления и разъяснения дефектов в C11. Стандартный макрос __STDC_VERSION__
определяется как 201710L
.
C2x
C2x - неофициальное название следующей (после C17) основной версии стандарта языка C. Ожидается, что голосование состоится не раньше декабря 2021 года.
Встроенный C
Исторически сложилось так, что встроенное программирование на C требует нестандартных расширений языка C для поддержки экзотических функций, таких как арифметика с фиксированной точкой, несколько отдельных банков памяти и базовые операции ввода-вывода.
В 2008 году Комитет по стандартам C опубликовал технический отчет о расширении языка C [21] для решения этих проблем путем предоставления общего стандарта для всех реализаций, которого должны придерживаться. Он включает в себя ряд функций, недоступных в обычном C, таких как арифметика с фиксированной точкой , именованные адресные пространства и базовая аппаратная адресация ввода-вывода.
Синтаксис
C имеет формальную грамматику, определенную стандартом C. [22] Окончания строк в C обычно не имеют значения; однако границы строк действительно имеют значение на этапе предварительной обработки. Комментарии могут появляться либо между разделителями /*
и */
, либо (начиная с C99) //
до конца строки. Комментарии разграничены /*
и */
не гнездится, и эти последовательности символов не интерпретируются как комментарий разделители , если они появляются внутри строку или символьные литералы. [23]
Исходные файлы C содержат объявления и определения функций. Определения функций, в свою очередь, содержат объявления и операторы . Объявления либо определяют новые типы с помощью таких ключевых слов, как struct
, union
и enum
, либо присваивают типы и, возможно, резервируют хранилище для новых переменных, обычно путем записи типа, за которым следует имя переменной. Ключевые слова, такие как char
и int
определяют встроенные типы. Разделы кода заключаются в фигурные скобки ( {
и }
иногда их называют «фигурными скобками»), чтобы ограничить объем объявлений и действовать как единый оператор для управляющих структур.
В качестве императивного языка C использует операторы для определения действий. Наиболее распространенный оператор - это оператор выражения , состоящий из выражения, которое нужно вычислить, за которым следует точка с запятой; в качестве побочного эффекта оценки могут быть вызваны функции и переменным могут быть присвоены новые значения. Чтобы изменить нормальное последовательное выполнение операторов, C предоставляет несколько операторов потока управления, идентифицированных зарезервированными ключевыми словами. Структурное программирование поддерживается if
(- else
) условное исполнение и do
- while
, while
и for
итеративного выполнения (обхвата). Этот for
оператор имеет отдельные выражения инициализации, тестирования и повторной инициализации, любое или все из которых можно опустить. break
и continue
может использоваться для выхода из самого внутреннего оператора включающего цикла или перехода к его повторной инициализации. Существует также неструктурированный goto
оператор, который ведет непосредственно к назначенной метке внутри функции. switch
выбирает case
для выполнения на основе значения целочисленного выражения.
Выражения могут использовать множество встроенных операторов и могут содержать вызовы функций. Порядок, в котором оцениваются аргументы функций и операнды для большинства операторов, не указан. Оценки могут даже чередоваться. Однако все побочные эффекты (включая сохранение переменных) будут происходить до следующей « точки последовательности »; точки последовательности включают конец каждого оператора выражения, а также вход и выход из каждого вызова функции. Точки последовательности также происходят во время вычисления выражений , содержащих определенные операторы ( &&
, ||
, ?:
и оператор запятой ). Это позволяет компилятору в высокой степени оптимизировать объектный код, но требует, чтобы программисты на C уделяли больше внимания получению надежных результатов, чем это требуется для других языков программирования.
Керниган и Ричи говорят во введении к языку программирования C : «C, как и любой другой язык, имеет свои недостатки. У некоторых операторов неправильный приоритет; некоторые части синтаксиса могли бы быть лучше». [24] Стандарт C не пытался исправить многие из этих недостатков из-за воздействия таких изменений на уже существующее программное обеспечение.
Набор символов
Базовый набор символов исходного кода C включает следующие символы:
- Строчные и прописные буквы основного латинского алфавита ISO:
a
-z
A
-Z
- Десятичные цифры:
0
-9
- Графические персонажи:
! " # % & ' ( ) * + , - . / : ; < = > ? [ \ ] ^ _ { | } ~
- Пробельные символы : пробел , горизонтальная табуляция , вертикальная табуляция , подача формы , новая строка
Новая строка обозначает конец текстовой строки; он не обязательно должен соответствовать реальному одиночному символу, хотя для удобства C рассматривает его как один.
В строковых литералах можно использовать дополнительные многобайтовые символы, но они не являются полностью переносимыми . Последний стандарт C ( C11 ) позволяет переносимо встраивать многонациональные символы Unicode в исходный текст C с помощью \uXXXX
или \UXXXXXXXX
кодирования (где X
обозначает шестнадцатеричный символ), хотя эта функция еще не получила широкого распространения.
Базовый набор выполнения C символов содержат одни и те же символы, наряду с представлениями для предупреждения , забоя и возврата каретки . Запуск время поддержка расширенных наборов символов увеличились с каждым пересмотром стандарта C.
Зарезервированные слова
C89 имеет 32 зарезервированных слова, также известных как ключевые слова, которые не могут использоваться для каких-либо целей, кроме тех, для которых они предопределены:
auto
break
case
char
const
continue
default
do
double
else
enum
extern
float
for
goto
if
int
long
register
return
short
signed
sizeof
static
struct
switch
typedef
union
unsigned
void
volatile
while
C99 зарезервировал еще пять слов:
_Bool
_Complex
_Imaginary
inline
restrict
C11 зарезервировал еще семь слов: [25]
_Alignas
_Alignof
_Atomic
_Generic
_Noreturn
_Static_assert
_Thread_local
Большинство недавно зарезервированных слов начинаются с подчеркивания, за которым следует заглавная буква, потому что идентификаторы этой формы ранее были зарезервированы стандартом C для использования только реализациями. Поскольку существующий исходный код программы не должен использовать эти идентификаторы, это не повлияет, когда реализации C начнут поддерживать эти расширения языка программирования. Некоторые стандартные заголовки действительно определяют более удобные синонимы для подчеркнутых идентификаторов. Раньше язык включал зарезервированное слово, называемое entry
, но это редко реализовывалось, и теперь было удалено как зарезервированное слово. [26]
Операторы
C поддерживает богатый набор операторов , которые представляют собой символы, используемые в выражении для указания операций , которые необходимо выполнить при вычислении этого выражения. В C есть операторы для:
- арифметической : +, -, *, /,%
- задание :
=
- дополненное назначение :
+=
,-=
,*=
,/=
,%=
,&=
,|=
,^=
,<<=
,>>=
- побитовая логика :
~
,&
,|
,^
- битовые сдвиги :
<<
,>>
- булева логика :
!
,&&
,||
- условная оценка :
? :
- Тестирование равенство: ==,!=
- вызывающие функции :
( )
- инкремент и декремент :
++
,--
- Выбор члена :
.
,->
- размер объекта:
sizeof
- отношения порядка :
<
,<=
,>
,>=
- ссылки и разыменовать :
&
,*
,[ ]
- последовательность действий: ,
- группировка подвыражений :
( )
- преобразование типов :
(typename)
C использует оператор =
(используемый в математике для выражения равенства) для обозначения присваивания, следуя прецеденту Fortran и PL / I , но в отличие от ALGOL и его производных. C использует оператор ==
для проверки равенства. Сходство между этими двумя операторами (присваивание и равенство) может привести к случайному использованию одного вместо другого, и во многих случаях ошибка не вызывает сообщения об ошибке (хотя некоторые компиляторы выдают предупреждения). Например, условное выражение if (a == b + 1)
может быть ошибочно записано как if (a = b + 1)
, которое будет оценено как истинное, если a
после присвоения не будет равно нулю. [27]
Приоритет оператора C не всегда интуитивно понятен. Например, оператор ==
связывает более жестко, чем (выполняется до) операторы &
(побитовое И) и |
(побитовое ИЛИ) в таких выражениях, как x & 1 == 0
, которые должны быть записаны так, как (x & 1) == 0
если бы это было намерением кодировщика. [28]
Пример "Привет, мир"
Пример " hello, world ", появившийся в первом издании K&R , стал моделью для вводной программы в большинстве учебников по программированию. Программа выводит «привет, мир» на стандартный вывод , который обычно представляет собой дисплей терминала или экран.
Исходная версия была: [29]
main () { printf ( "привет, мир \ п " ); }
Соответствующая стандартам программа "Hello, world": [a]
#include int main ( void ) { printf ( "привет, мир \ п " ); }
Первая строка программы содержит директиву предварительной обработки , обозначенную значком #include
. Это заставляет компилятор заменять эту строку полным текстом stdio.h
стандартного заголовка, который содержит объявления для стандартных функций ввода и вывода, таких как printf
и scanf
. Окружающие угловые скобки stdio.h
указывают на то, что stdio.h
используется стратегия поиска, которая предпочитает заголовки, предоставленные с компилятором, другим заголовкам с тем же именем, в отличие от двойных кавычек, которые обычно включают локальные или специфичные для проекта файлы заголовков.
Следующая строка указывает на то, что определена названная функция main
. Эта main
функция служит специальной цели в программах на языке C; среда выполнения вызывает main
функцию, чтобы начать выполнение программы. Спецификатор типа int
указывает, что значение, возвращаемое вызывающей стороне (в данном случае среде выполнения) в результате оценки main
функции, является целым числом. Ключевое слово void
как список параметров указывает, что эта функция не принимает аргументов. [b]
Открывающая фигурная скобка указывает на начало определения main
функции.
Следующая строка вызывает (перенаправляет выполнение) названную функцию printf
, которая в данном случае предоставляется из системной библиотеки . В этом вызове printf
функции передается (предоставляется) единственный аргумент - адрес первого символа строкового литерала "hello, world\n"
. Строковый литерал представляет собой безымянный массив с элементами типа char
, автоматически настраиваемый компилятором с заключительным нулевым символом для обозначения конца массива ( printf
необходимо знать это). \n
Представляет собой последовательность символов , что С переводит к новой строке символу, который на выходе означает конец текущей строки. Возвращаемое значение printf
функции относится к типу int
, но оно автоматически отбрасывается, поскольку не используется. (Более тщательная программа могла бы проверить возвращаемое значение, чтобы определить, printf
успешно ли выполнена функция.) Точка с запятой ;
завершает оператор.
Закрывающая фигурная скобка указывает конец кода main
функции. Согласно спецификации C99 и новее, main
функция, в отличие от любой другой функции, будет неявно возвращать значение 0
при достижении того, }
что завершает функцию. (Раньше return 0;
требовался явный оператор.) Это интерпретируется системой времени выполнения как код выхода, указывающий на успешное выполнение. [30]
Типы данных
Система типов в C является статической и слабо типизированной , что делает ее похожей на систему типов потомков АЛГОЛА, таких как Паскаль . [31] Существуют встроенные типы для целых чисел разного размера, как со знаком, так и без знака, числа с плавающей запятой и перечислимые типы ( enum
). Целочисленный тип char
часто используется для однобайтовых символов. C99 добавил логический тип данных . Существуют также производные типы, включая массивы , указатели , записи ( struct
) и объединения ( union
).
C часто используется в низкоуровневом системном программировании, где может потребоваться выход из системы типов. Компилятор пытается обеспечить правильность типа большинства выражений, но программист может переопределить проверки различными способами, либо используя приведение типа для явного преобразования значения из одного типа в другой, либо используя указатели или объединения для переинтерпретации базовых битов. объекта данных другим способом.
Некоторые находят синтаксис объявления C неинтуитивным, особенно для указателей на функции . (Идея Ричи заключалась в объявлении идентификаторов в контексте, напоминающем их использование: « объявление отражает использование ».) [32]
Обычные арифметические преобразования C позволяют генерировать эффективный код, но иногда могут давать неожиданные результаты. Например, сравнение знаковых и беззнаковых целых чисел одинаковой ширины требует преобразования знакового значения в беззнаковое. Это может привести к неожиданным результатам, если значение со знаком отрицательное.
Указатели
C поддерживает использование указателей , типа ссылки, которая записывает адрес или расположение объекта или функции в памяти. Указатели могут быть разыменованы для доступа к данным, хранящимся по указанному адресу, или для вызова указанной функции. Указателями можно управлять с помощью присваивания или арифметики указателя . Представление значения указателя во время выполнения обычно представляет собой необработанный адрес памяти (возможно, дополненный полем смещения внутри слова), но поскольку тип указателя включает тип объекта, на который указывает, выражения, включающие указатели, могут быть проверены по типу во время компиляции. Арифметика указателя автоматически масштабируется по размеру указанного типа данных. Указатели используются для многих целей в C. Текстовые строки обычно обрабатываются с помощью указателей на массивы символов. Распределение динамической памяти выполняется с помощью указателей. Многие типы данных, такие как деревья , обычно реализуются как динамически выделяемые struct
объекты, связанные вместе с помощью указателей. Указатели на функции полезны для передачи функций в качестве аргументов функциям более высокого порядка (таким как qsort или bsearch ) или как обратные вызовы, вызываемые обработчиками событий. [30]
Указатель NULL значение явно не указывает ни действительного местоположения. Разыменование значения нулевого указателя не определено, что часто приводит к ошибке сегментации . Значения нулевого указателя полезны для указания особых случаев, таких как отсутствие указателя «следующий» в последнем узле связанного списка , или как указание на ошибку от функций, возвращающих указатели. В соответствующих контекстах исходного кода, например для присвоения переменной- указателю, константа нулевого указателя может быть записана как 0
с явным приведением к типу указателя или без него, или как NULL
макрос, определенный несколькими стандартными заголовками. В условных контекстах значения нулевого указателя оцениваются как ложные, в то время как все другие значения указателей оцениваются как истинные.
Пустые указатели ( void *
) указывают на объекты неопределенного типа и поэтому могут использоваться как «общие» указатели на данные. Поскольку размер и тип указанного объекта неизвестны, указатели void не могут быть разыменованы, а арифметика указателей на них не разрешена, хотя они могут быть легко (и во многих контекстах неявно) преобразованы в любой другой указатель объекта и из него. тип. [30]
Небрежное использование указателей потенциально опасно. Поскольку они обычно не отмечены, переменная-указатель может указывать на любое произвольное место, что может вызвать нежелательные эффекты. Хотя правильно используемые указатели указывают на безопасные места, их можно сделать так, чтобы они указывали на небезопасные места, используя арифметику неверных указателей ; объекты, на которые они указывают, могут продолжать использоваться после освобождения ( висячие указатели ); их можно использовать без инициализации ( дикие указатели ); либо им может быть прямо присвоено небезопасное значение с помощью приведения, объединения или другого поврежденного указателя. В общем, C допускает манипулирование и преобразование между типами указателей, хотя компиляторы обычно предоставляют варианты для различных уровней проверки. Некоторые другие языки программирования решают эти проблемы, используя более ограничительные ссылочные типы.
Массивы
Типы массивов в C обычно имеют фиксированный статический размер, указанный во время компиляции. (Более поздний стандарт C99 также допускает форму массивов переменной длины.) Однако также можно выделить блок памяти (произвольного размера) во время выполнения, используя malloc
функцию стандартной библиотеки , и рассматривать его как множество. Унификация массивов и указателей в языке C означает, что объявленные массивы и эти динамически распределяемые моделируемые массивы практически взаимозаменяемы.
Поскольку доступ к массивам всегда (фактически) осуществляется через указатели, доступ к массивам обычно не проверяется по размеру базового массива, хотя некоторые компиляторы могут предоставлять проверку границ в качестве опции. [33] [34] Таким образом, нарушение границ массива возможно и довольно часто встречается в небрежно написанном коде и может привести к различным последствиям, включая незаконный доступ к памяти, повреждение данных, переполнение буфера и исключения времени выполнения. Если требуется проверка границ, это необходимо сделать вручную.
C не имеет специального положения для объявления многомерных массивов , но полагается на рекурсию в системе типов для объявления массивов массивов, что фактически выполняет то же самое. Значения индекса результирующего «многомерного массива» можно рассматривать как возрастающие в порядке возрастания строк .
Многомерные массивы обычно используются в численных алгоритмах (в основном из прикладной линейной алгебры ) для хранения матриц. Структура массива C хорошо подходит для этой конкретной задачи. Однако, поскольку массивы передаются просто как указатели, границы массива должны быть известными фиксированными значениями или же явно передаваться любой подпрограмме, которая их требует, а к массивам массивов с динамическим размером нельзя получить доступ с помощью двойной индексации. (Обходной путь для этого - выделить массив с дополнительным "вектором-строкой" указателей на столбцы.)
C99 представил «массивы переменной длины», которые решают некоторые, но не все, проблемы с обычными массивами C.
Взаимозаменяемость массива и указателя
Обозначение индекса x[i]
(где x
обозначает указатель) является синтаксическим сахаром для *(x+i)
. [35] Воспользовавшись знанием компилятора о типе указателя, адрес, на который x + i
указывает, не является базовым адресом (на который указывает x
), увеличенным на i
байты, а скорее определяется как базовый адрес, увеличенный на i
умноженный на размер элемент, x
указывающий на. Таким образом, x[i]
обозначает i+1
th элемент массива.
Более того, в большинстве контекстов выражений (заметным исключением является операнд sizeof
) имя массива автоматически преобразуется в указатель на первый элемент массива. Это означает, что массив никогда не копируется целиком, когда он назван в качестве аргумента функции, а передается только адрес его первого элемента. Следовательно, хотя вызовы функций в C используют семантику передачи по значению , массивы фактически передаются по ссылке .
Размер элемента можно определить, применив оператор sizeof
к любому разыменованному элементу x
, как в n = sizeof *x
или n = sizeof x[0]
, а количество элементов в объявленном массиве A
может быть определено как sizeof A / sizeof A[0]
. Последнее относится только к именам массивов: переменным, объявленным с помощью индексов ( int A[20]
). Из-за семантики C невозможно определить полный размер массивов с помощью указателей на массивы, таких как массивы, созданные с помощью динамического выделения ( malloc
) или параметров функции массива; такой код, как sizeof arr / sizeof arr[0]
(где arr
обозначает указатель) не будет работать, поскольку компилятор предполагает, что запрашивается размер самого указателя. [36] [37] Поскольку аргументы имени массива sizeof
не преобразуются в указатели, они не проявляют такой двусмысленности. Однако к массивам, созданным с помощью динамического выделения, обращаются указатели, а не истинные переменные массива, поэтому они страдают теми же sizeof
проблемами, что и указатели на массивы.
Таким образом, несмотря на эту очевидную эквивалентность между переменными массива и указателя, все же необходимо проводить различие между ними. Несмотря на то, что имя массива в большинстве контекстов выражения преобразуется в указатель (на его первый элемент), этот указатель сам по себе не занимает никакой памяти; имя массива не является l-значением , а его адрес является константой, в отличие от переменной-указателя. Следовательно, то, на что «указывает» массив, не может быть изменено, и невозможно присвоить новый адрес имени массива. Однако содержимое массива можно скопировать с помощью memcpy
функции или доступа к отдельным элементам.
Управление памятью
Одна из наиболее важных функций языка программирования - предоставить средства для управления памятью и объектами, которые хранятся в памяти. C предоставляет три различных способа выделения памяти для объектов: [30]
- Распределение статической памяти : пространство для объекта предоставляется в двоичном коде во время компиляции; эти объекты имеют размер (или время жизни) до тех пор, пока содержащий их двоичный файл загружен в память.
- Автоматическое выделение памяти : временные объекты могут храниться в стеке , и это пространство автоматически освобождается и может использоваться повторно после выхода из блока, в котором они объявлены.
- Динамическое выделение памяти : блоки памяти произвольного размера могут запрашиваться во время выполнения с использованием библиотечных функций, например,
malloc
из области памяти, называемой кучей ; эти блоки сохраняются до тех пор, пока впоследствии не будут освобождены для повторного использования путем вызова библиотечной функцииrealloc
илиfree
Эти три подхода подходят в разных ситуациях и имеют разные компромиссы. Например, выделение статической памяти имеет небольшие накладные расходы, автоматическое выделение может включать немного больше накладных расходов, а выделение динамической памяти потенциально может иметь большие накладные расходы как для выделения, так и для освобождения. Постоянный характер статических объектов полезен для сохранения информации о состоянии между вызовами функций, автоматическое выделение легко использовать, но пространство стека обычно гораздо более ограничено и временное, чем статическая память или пространство кучи, а динамическое распределение памяти позволяет удобно выделять объекты, чьи размер известен только во время выполнения. Большинство программ на языке C широко используют все три.
Там, где это возможно, автоматическое или статическое распределение обычно является самым простым, поскольку хранилище управляется компилятором, освобождая программиста от потенциально подверженной ошибкам рутинной работы по выделению и освобождению хранилища вручную. Однако многие структуры данных могут изменяться по размеру во время выполнения, и поскольку статические выделения (и автоматические выделения до C99) должны иметь фиксированный размер во время компиляции, существует много ситуаций, в которых необходимо динамическое выделение. [30] До стандарта C99 типичным примером этого были массивы переменного размера. (См. В статье malloc
пример динамически выделяемых массивов.) В отличие от автоматического выделения, которое может дать сбой во время выполнения с неконтролируемыми последствиями, функции динамического выделения возвращают указание (в виде значения нулевого указателя), когда требуемое хранилище не может быть выделенным. (Слишком большое статическое выделение памяти обычно обнаруживается компоновщиком или загрузчиком еще до того, как программа сможет начать выполнение.)
Если не указано иное, статические объекты содержат нулевые или нулевые значения указателей при запуске программы. Автоматически и динамически выделяемые объекты инициализируются только в том случае, если явно указано начальное значение; в противном случае они изначально имеют неопределенные значения (как правило, любой битовый шаблон , присутствующий в хранилище , может даже не представлять допустимое значение для этого типа). Если программа пытается получить доступ к неинициализированному значению, результаты не определены. Многие современные компиляторы пытаются обнаружить и предупредить об этой проблеме, но могут возникать как ложные срабатывания, так и ложноотрицательные .
Выделение памяти в куче должно быть синхронизировано с ее фактическим использованием в любой программе, чтобы ее можно было повторно использовать в максимально возможной степени. Например, если единственный указатель на выделение памяти в куче выходит за пределы области видимости или его значение перезаписывается до того, как оно будет явно освобождено, то эта память не может быть восстановлена для последующего повторного использования и по существу потеряна для программы, явление, известное как память утечка . И наоборот, память может быть освобождена, но на нее впоследствии будут ссылаться, что приведет к непредсказуемым результатам. Обычно симптомы сбоя появляются в части программы, не связанной с кодом, вызывающим ошибку, что затрудняет диагностику сбоя. Такие проблемы устраняются в языках с автоматической сборкой мусора .
Библиотеки
Язык программирования C использует библиотеки в качестве основного метода расширения. В C библиотека - это набор функций, содержащихся в одном «архивном» файле. Каждая библиотека обычно имеет файл заголовка , который содержит прототипы функций, содержащихся в библиотеке, которые могут использоваться программой, а также объявления специальных типов данных и макросимволов, используемых с этими функциями. Чтобы программа могла использовать библиотеку, она должна включать файл заголовка библиотеки, и библиотека должна быть связана с программой, что во многих случаях требует наличия флагов компилятора (например -lm
, сокращение для «связать математическую библиотеку»). [30]
Наиболее распространенной библиотекой C является стандартная библиотека C , которая определяется стандартами ISO и ANSI C и поставляется с каждой реализацией C (реализации, предназначенные для ограниченных сред, таких как встроенные системы, могут предоставлять только подмножество стандартной библиотеки). Эта библиотека поддерживает потоковый ввод и вывод, распределение памяти, математику, символьные строки и значения времени. Несколько отдельных стандартных заголовков (например, stdio.h
) определяют интерфейсы для этих и других средств стандартной библиотеки.
Другой распространенный набор функций библиотеки C - это те, которые используются приложениями, специально предназначенными для Unix и Unix-подобных систем, особенно функции, которые обеспечивают интерфейс с ядром . Эти функции подробно описаны в различных стандартах, таких как POSIX и Single UNIX Specification .
Поскольку многие программы написаны на C, доступно множество других библиотек. Библиотеки часто пишутся на C, потому что компиляторы C генерируют эффективный объектный код ; Затем программисты создают интерфейсы к библиотеке, чтобы можно было использовать подпрограммы из языков более высокого уровня, таких как Java , Perl и Python . [30]
Обработка файлов и потоки
Файловый ввод и вывод (I / O) не является частью самого языка C, но вместо этого обрабатывается библиотеками (такими как стандартная библиотека C) и связанными с ними файлами заголовков (например stdio.h
). Обработка файлов обычно осуществляется через высокоуровневый ввод-вывод, который работает через потоки . С этой точки зрения поток - это поток данных, который не зависит от устройств, а файл - это конкретное устройство. Ввод-вывод высокого уровня выполняется через ассоциацию потока с файлом. В стандартной библиотеке C буфер (область памяти или очередь) временно используется для хранения данных перед их отправкой в конечный пункт назначения. Это сокращает время ожидания более медленных устройств, например жесткого диска или твердотельного накопителя . Функции низкоуровневого ввода-вывода не являются частью стандартной библиотеки C, но обычно являются частью "голого" программирования (программирования, которое не зависит от какой-либо операционной системы, например, большинства, но не всех встроенных программ ). За некоторыми исключениями, реализации включают в себя низкоуровневый ввод-вывод.
Языковые инструменты
Ряд инструментов был разработан, чтобы помочь программистам на C находить и исправлять операторы с неопределенным поведением или, возможно, ошибочными выражениями, с большей строгостью, чем та, которая предоставляется компилятором. Инструмент lint был первым из них, за ним последовало множество других.
Автоматическая проверка и аудит исходного кода полезны для любого языка, и для C существует множество таких инструментов, например Lint . Распространенной практикой является использование Lint для обнаружения сомнительного кода при первом написании программы. Как только программа проходит Lint, она компилируется с помощью компилятора C. Кроме того, многие компиляторы могут дополнительно предупреждать о синтаксически правильных конструкциях, которые могут быть ошибками. MISRA C - это проприетарный набор рекомендаций, позволяющий избежать такого сомнительного кода, разработанный для встраиваемых систем. [38]
Существуют также компиляторы, библиотеки и механизмы уровня операционной системы для выполнения действий, которые не являются стандартной частью C, таких как проверка границ для массивов, обнаружение переполнения буфера , сериализация , отслеживание динамической памяти и автоматическая сборка мусора .
Такие инструменты, как Purify или Valgrind, и связывание с библиотеками, содержащими специальные версии функций распределения памяти, могут помочь выявить ошибки времени выполнения в использовании памяти.
Использует
C широко используется для системного программирования при реализации операционных систем и встраиваемых системных приложений [40], потому что код C, написанный для переносимости, может использоваться для большинства целей, но при необходимости системно-специфический код может использоваться для доступа к конкретному оборудованию. адресов и для выполнения набора текста в соответствии с внешними требованиями к интерфейсу с низким требованием времени выполнения к системным ресурсам.
C может использоваться для программирования веб-сайтов с использованием Common Gateway Interface (CGI) в качестве «шлюза» для обмена информацией между веб-приложением, сервером и браузером. [41] C часто предпочитают интерпретируемым языкам из-за его скорости, стабильности и почти универсальной доступности. [42]
Следствие широкой доступности и эффективности C является то , что компиляторы , библиотека и переводчики других языков программирования часто реализуются в С. Например, ссылка реализация на Python , Perl и PHP написана на C.
C позволяет программистам создавать эффективные реализации алгоритмов и структур данных, потому что уровень абстракции от оборудования тонкий, а его накладные расходы низкие, что является важным критерием для программ с интенсивными вычислениями. Например, GNU Multiple Precision Арифметика библиотека , то GNU научная библиотека , Mathematica , и MATLAB полностью или частично написаны на C.
C иногда используется в качестве промежуточного языка при реализации других языков. Этот подход может использоваться для портативности или удобства; при использовании C в качестве промежуточного языка дополнительные машинно-зависимые генераторы кода не требуются. C имеет некоторые функции, такие как директивы препроцессора для номеров строк и необязательные лишние запятые в конце списков инициализаторов, которые поддерживают компиляцию сгенерированного кода. Однако некоторые недостатки C побудили к разработке других языков на основе C, специально предназначенных для использования в качестве промежуточных языков, таких как C-- .
C также широко используется для реализации приложений для конечных пользователей . Однако такие приложения также могут быть написаны на более новых языках высокого уровня.
Родственные языки
C прямо и косвенно повлиял на многие более поздние языки, такие как C # , D , Go , Java , JavaScript , Limbo , LPC , Perl , PHP , Python и оболочку C Unix . [43] Наиболее распространенное влияние было синтаксическим; все упомянутые языки сочетают синтаксис операторов и (более или менее узнаваемых) выражений языка Си с системами типов, моделями данных и / или крупномасштабными программными структурами, которые иногда радикально отличаются от таковых в Си.
Существует несколько интерпретаторов C или близких к C, включая Ch и CINT , которые также можно использовать для написания сценариев.
Когда стали популярными объектно-ориентированные языки, C ++ и Objective-C были двумя разными расширениями C, которые обеспечивали объектно-ориентированные возможности. Оба языка изначально были реализованы как компиляторы «исходный код» ; исходный код был переведен на C, а затем скомпилирован с помощью компилятора C. [44]
Язык программирования C ++ был разработан Бьярном Страуструпом как подход к обеспечению объектно-ориентированной функциональности с синтаксисом, подобным Си. [45] C ++ добавляет большую силу набора, область видимости и другие инструменты, полезные в объектно-ориентированном программировании, и разрешает универсальное программирование с помощью шаблонов. Почти надмножество C, C ++ теперь поддерживает большую часть C, за некоторыми исключениями .
Objective-C изначально был очень «тонким» слоем поверх C и остается строгим надмножеством C, позволяющим объектно-ориентированное программирование с использованием гибридной парадигмы динамической / статической типизации. Objective-C заимствует свой синтаксис как из C, так и из Smalltalk : синтаксис, который включает предварительную обработку, выражения, объявления функций и вызовы функций, унаследован от C, в то время как синтаксис для объектно-ориентированных функций был первоначально взят из Smalltalk.
В дополнение к C ++ и Objective-C , Ch , Cilk и Unified Parallel C являются почти надмножествами C.
Смотрите также
- Совместимость C и C ++
- Сравнение Паскаля и Си
- Сравнение языков программирования
- Международный конкурс запутанного кода C
- Список языков программирования на основе C
- Список компиляторов C
Заметки
- ^ Исходный пример кода будет компилироваться на большинстве современных компиляторов, которые не находятся в режиме строгого соответствия стандартам, но он не полностью соответствует требованиям C89 или C99. Фактически, C99 требует выдачи диагностического сообщения.
- ^ Функциясамом деле имеет два аргумента,и, соответственно, которые могут быть использованы для обработки аргументов командной строки . Стандарт ISO C (раздел 5.1.2.2.1) требует поддержки обеих форм, что является особым подходом, не предусмотренным для каких-либо других функций.
main
int argc
char *argv[]
main
Рекомендации
- ^ а б Керниган, Брайан В .; Ричи, Деннис М. (февраль 1978 г.). Язык программирования C (1-е изд.). Энглвуд Клиффс, Нью-Джерси : Prentice Hall . ISBN 978-0-13-110163-0.
- ^ Ritchie (1993) : «Томпсон предпринял краткую попытку создать систему, закодированную в ранней версии C - до структур - в 1972 году, но отказался от этой попытки».
- ^ Фрудерика (13 декабря 2020 г.). «История C» . Сайт cppreference.com . Проверено 24 октября 2020 года .
- ^ Ritchie (1993) : «Схема набора шрифтов, принятая C, в значительной степени обязана Алголу 68, хотя, возможно, она не возникла в форме, которую одобрили бы приверженцы Алгола».
- ^ а б "Verilog HDL (и C)" (PDF) . Исследовательская школа компьютерных наук Австралийского национального университета. 3 июня 2010 года Архивировано из оригинального (PDF) 6 ноября 2013 года . Проверено 19 августа 2013 года .
1980-е годы:; Впервые представлен Verilog; Verilog вдохновлен языком программирования C
- ^ a b c d Ричи (1993)
- ^ «Популярность языков программирования» . 2009. Архивировано из оригинала 16 января 2009 года . Проверено 16 января 2009 года .
- ^ "Индекс сообщества программистов TIOBE" . 2009. Архивировано из оригинала 4 мая 2009 года . Проверено 6 мая 2009 года .
- ^ «Индекс TIOBE за январь 2021 года» . Архивировано 12 января 2021 года . Проверено 19 января 2021 года .
- ^ «История C» . en.cppreference.com .
- ^ Ричи, Деннис. «BCPL к B к C» .
- ^ а б Джонсон, Южная Каролина ; Ричи, DM (1978). «Переносимость программ C и системы UNIX». Bell System Tech. Дж . 57 (6): 2021–2048. CiteSeerX 10.1.1.138.35 . DOI : 10.1002 / j.1538-7305.1978.tb02141.x . S2CID 17510065 . (Примечание: PDF-файл представляет собой сканированное изображение оригинала с оптическим распознаванием символов и содержит отрисовку IBM 370 как IBM 310.)
- ^ Макилрой, доктор медицины (1987). Читатель Research Unix: аннотированные выдержки из Руководства программиста, 1971–1986 (PDF) (технический отчет). CSTR. Bell Labs. п. 10. 139.
- ↑ Ричи (1993)
- ^ "Справочные страницы C". Руководство по разной информации FreeBSD (FreeBSD 13.0 ed.). 30 мая 2011 г. [1]
- ^ Керниган, Брайан В .; Ричи, Деннис М. (март 1988 г.). Язык программирования C (2-е изд.). Энглвуд Клиффс, Нью-Джерси : Prentice Hall . ISBN 978-0-13-110362-7.
- ^ Страуструп, Бьярн (2002). Соперничество братьев и сестер: C и C ++ (PDF) (Отчет). AT&T Labs.
- ^ C Целостность . Международная Организация Стандартизации. 30 марта 1995 г.
- ^ "JTC1 / SC22 / WG14 - C" . Домашняя страница . ИСО / МЭК . Проверено 2 июня 2011 года .
- ^ Эндрю Бинсток (12 октября 2011 г.). «Интервью с Хербом Саттером» . Доктор Доббс . Проверено 7 сентября 2013 года .
- ^ «TR 18037: Встроенный C» (PDF) . ИСО / МЭК . Проверено 26 июля 2011 года .
- ^ Harbison, Samuel P .; Стил, Гай Л. (2002). C: Справочное руководство (5-е изд.). Энглвуд Клиффс, Нью-Джерси : Prentice Hall . ISBN 978-0-13-089592-9.Содержит грамматику BNF для C.
- ^ Керниган и Ричи (1996) , стр. 192.
- ^ Керниган и Ричи (1978) , стр. 3.
- ^ «Проект комитета ISO / IEC 9899: 201x (ISO C11)» (PDF) .
- ^ Керниган & Ритчи (1996) , стр. 192, 259.
- ^ «10 распространенных ошибок программирования на C ++» . Cs.ucr.edu . Проверено 26 июня 2009 года .
- ^ Шульц, Томас (2004). C и 8051 (3-е изд.). Отсего, Мичиган: PageFree Publishing Inc. стр. 20. ISBN 978-1-58961-237-2. Проверено 10 февраля 2012 года .
- ^ Керниган и Ричи (1978) , стр. 6.
- ^ Б с д е е г Клеменс, Бен (2013). С 21 - го века . O'Reilly Media . ISBN 978-1-4493-2714-9.
- ^ Feuer, Alan R .; Гехани, Нараин Х. (март 1982 г.). «Сравнение языков программирования C и Pascal». ACM Computing Surveys . 14 (1): 73–92. DOI : 10.1145 / 356869.356872 . S2CID 3136859 .
- ^ Керниган и Ричи (1996) , стр. 122.
- ^ Например, gcc предоставляет _FORTIFY_SOURCE. «Функции безопасности: проверки буфера времени компиляции (FORTIFY_SOURCE)» . fedoraproject.org . Проверено 5 августа 2012 года .
- ^ เอี่ยม สิริ วงศ์, โอภา ศ (2016). Программирование с использованием C . Бангкок, Таиланд: SE-EDUCATION PUBLIC COMPANY LIMITED. С. 225–230. ISBN 978-616-08-2740-4.
- ^ Раймонд, Эрик С. (11 октября 1996 г.). Словарь нового хакера (3-е изд.). MIT Press. п. 432. ISBN. 978-0-262-68092-9. Проверено 5 августа 2012 года .
- ^ Саммит, Стив. «comp.lang.c Часто задаваемые вопросы 6.23» . Проверено 6 марта 2013 года .
- ^ Саммит, Стив. «comp.lang.c Часто задаваемые вопросы 7.28» . Проверено 6 марта 2013 года .
- ^ «Man Page для lint (Freebsd Раздел 1)» . unix.com . 24 мая 2001 . Проверено 15 июля 2014 года .
- ^ Макмиллан, Роберт (1 августа 2013 г.). "Ява теряет свой моджо?" . Проводной .
- ^ Дейл, Нелл Б.; Уимс, Чип (2014). Программирование и решение задач с помощью C ++ (6-е изд.). Берлингтон, Массачусетс: Jones & Bartlett Learning. ISBN 978-1449694289. OCLC 894992484 .
- ^ Справочник доктора Добба . США: Miller Freeman, Inc., ноябрь – декабрь 1995 г.
- ^ «Использование C для программирования CGI» . linuxjournal.com. 1 марта 2005 . Проверено 4 января 2010 года .
- ^ О'Реган, Джерард (24 сентября 2015 г.). Столпы вычислительной техники: сборник избранных ключевых технологических компаний . ISBN 978-3319214641. OCLC 922324121 .
- ^ Раухвергер, Лоуренс (2004). Языки и компиляторы для параллельных вычислений: 16-й международный семинар, LCPC 2003, Колледж-Стейшн, Техас, США, 2-4 октября 2003 г .: исправленные статьи . Springer. ISBN 978-3540246442. OCLC 57965544 .
- ^ Страуструп, Бьярн (1993). «История C ++: 1979–1991» (PDF) . Проверено 9 июня 2011 года .
Источники
- Ричи, Деннис М. (март 1993 г.). «Развитие языка Си». Уведомления ACM SIGPLAN . ACM. 28 (3): 201–208. DOI : 10.1145 / 155360.155580 .
Ричи, Деннис М. (1993). «Развитие языка Си» . Вторая конференция ACM SIGPLAN по истории языков программирования (HOPL-II) . ACM . С. 201–208. DOI : 10.1145 / 154766.155580 . ISBN 0-89791-570-4. Проверено 4 ноября 2014 года . - Керниган, Брайан В .; Ричи, Деннис М. (1996). Язык программирования C (2-е изд.). Прентис Холл . ISBN 7-302-02412-X.
дальнейшее чтение
- Керниган, Брайан ; Ричи, Деннис (1988). Язык программирования C (2-е изд.). Прентис Холл. ISBN 978-0131103627. (архив)
- Plauger, PJ (1992). Стандартная библиотека C (1-е изд.). Прентис Холл. ISBN 978-0131315099. (источник)
- Banahan, M .; Brady, D .; Доран, М. (1991). Книга C: Показывая Стандарт ANSI C (2-е изд.). Эддисон-Уэсли. ISBN 978-0201544336. (бесплатно)
- Харбисон, Самуэль; Стил-младший, Гай (2002). C: Справочное руководство (5-е изд.). Пирсон. ISBN 978-0130895929. (архив)
- Кинг, KN (2008). Программирование на C: современный подход (2-е изд.). WW Нортон. ISBN 978-0393979503. (архив)
- Гриффитс, Дэвид; Гриффитс, Рассвет (2012). Head First C (1-е изд.). О'Рейли. ISBN 978-1449399917.
- Перри, Грег; Миллер, Дин (2013). Программирование на C: Абсолютное руководство для начинающих (3-е изд.). Que. ISBN 978-0789751980.
- Дейтель, Пол; Дейтель, Харви (2015). C: Как программировать (8-е изд.). Пирсон. ISBN 978-0133976892.
- Густедт, Йенс (2019). Современный C (2-е изд.). Укомплектование персоналом. ISBN 978-1617295812. (бесплатно)
Внешние ссылки
- Официальный сайт рабочей группы ISO C
- ISO / IEC 9899 , общедоступные официальные документы C, включая C99 Rationale
- «C99 с техническими исправлениями TC1, TC2 и TC3 включены» (PDF) . (3,61 МБ)
- comp.lang.c Часто задаваемые вопросы
- История C , Деннис Ричи