Язык программирования C невероятно популярен, и легко понять почему. Программирование на C эффективно и дает программисту большой контроль. Многие другие языки программирования, такие как C ++, Java и Python, были разработаны с использованием C.
С каждым днем возрастают шансы, что если вы программист, вы не будете использовать C исключительно для своей работы. Однако в некоторых случаях изучение C очень полезно, даже если вы не используете его регулярно. Вот почему:
Вы сможете читать и писать код для программного обеспечения, которое можно использовать на самых разных типах компьютерных платформ, включая все, от небольших микроконтроллеров до настольных, портативных и мобильных операционных систем.
Вы лучше поймете, что языки высокого уровня делают за кулисами, например, управление памятью и сборку мусора. Это понимание может помочь вам писать программы, которые работают более эффективно.
Если вы специалист по информационным технологиям (ИТ), вам также может пригодиться изучение C. ИТ-специалисты часто пишут, поддерживают и запускают сценарии в рамках своей работы. Сценарий представляет собой список инструкций для операционной системы компьютера , чтобы следовать. Для запуска определенных сценариев компьютер устанавливает контролируемую среду выполнения, называемую оболочкой . Поскольку большинство операционных систем запускают оболочки на основе C, оболочка C является популярной адаптацией сценариев языка C, используемой ИТ-специалистами.
В этой статье рассказывается об истории C, рассматривается, почему C так важен, показаны примеры базового кода C и исследуются некоторые важные особенности C, включая типы данных, операции, функции, указатели и управление памятью. Хотя эта статья не является инструкцией по программированию на C, она охватывает то, что делает программирование на C уникальным и выходит за рамки первых нескольких глав среднего руководства по программированию на C.
Давайте начнем с того, что посмотрим, откуда появился язык программирования C, как он развивался и какую роль он играет в разработке программного обеспечения сегодня.
- Что такое C?
- Редактирование и компиляция кода C
- Простейшая программа на C
- Общие концепции программирования на C
- Функции в C
- Функциональные прототипы
- Типы данных и операции в C
- Не начинайте с нуля, используйте библиотеки
- Некоторые указатели на указатели в C
- Правильное использование указателей в C
- Важность управления памятью в C
Что такое C?
Самый простой способ определить C - это назвать его языком компьютерного программирования, что означает, что вы можете писать с его помощью программное обеспечение, которое может выполнять компьютер. Результатом может быть большое компьютерное приложение, такое как ваш веб-браузер, или крошечный набор инструкций, встроенный в микропроцессор или другой компьютерный компонент.
Язык C был разработан в начале 1970-х годов в Bell Laboratories, в первую очередь благодаря работе Кена Томпсона и Денниса Ричи. Программистам требовался более удобный набор инструкций для операционной системы UNIX, которая в то время требовала программ, написанных на языке ассемблера. Программы сборки, которые обращаются непосредственно к аппаратному обеспечению компьютера, длительны и трудны для отладки, и они требуют утомительной и трудоемкой работы по добавлению новых функций [источник: King].
Первая попытка Томпсона создать язык высокого уровня была названа B, дань уважения языку системного программирования BCPL, на котором он был основан. Когда Bell Labs приобрела модель системы UNIX PDP-11 Digital Equipment Corporation (DEC), Томпсон переработал B, чтобы лучше соответствовать требованиям нового и лучшего системного оборудования. Таким образом, родился преемник B, C. К 1973 году C был достаточно стабилен, чтобы можно было переписать сам UNIX с использованием этого инновационного нового языка более высокого уровня [источник: King].
Прежде чем C можно было эффективно использовать за пределами Bell Labs, другим программистам требовался документ, объясняющий, как его использовать. В 1978 году книга Брайана Кернигана и Денниса Ричи «Язык программирования C», известная энтузиастами C как K&R или «Белая книга», стала исчерпывающим источником программирования на языке C. На момент написания этой статьи второе издание K&R, первоначально опубликованное в 1988 году, все еще широко доступно. Исходная, предварительная стандартная версия C называется K&R C на основе этой книги.
Чтобы люди не создавали свои собственные диалекты с течением времени, разработчики C работали на протяжении 1980-х годов над созданием стандартов для языка. Стандарт США для C, стандарт X3.159-1989 Американского национального института стандартов (ANSI), стал официальным в 1989 году. Стандарт Международной организации по стандартизации (ISO), ISO / IEC 9899: 1990, последовал в 1990 году. Версии C после того, как K&R ссылается на эти стандарты и их более поздние версии (C89, C90 и C99). Вы также можете увидеть C89, называемый «ANSI C», «ANSI / ISO C» или «ISO C.»
C и его использование в UNIX были лишь частью бума разработки операционных систем в 1980-х годах. Тем не менее, несмотря на все улучшения по сравнению с предшественниками, C все же было нелегко использовать для разработки более крупных программных приложений. По мере того, как компьютеры становились все более мощными, росла потребность в более простом программировании. Это требование побудило программистов создавать свои собственные компиляторы и, следовательно, свои собственные новые языки программирования с использованием C. Эти новые языки могли упростить кодирование сложных задач с большим количеством движущихся частей. Например, такие языки, как C ++ и Java, разработанные на основе C, упрощают объектно-ориентированное программирование, подход к программированию, который оптимизирует способность программиста повторно использовать код.
Теперь, когда вы немного знакомы с предысторией, давайте посмотрим на механику самого C.
Редактирование и компиляция кода C
C - это то, что называется скомпилированным языком, что означает, что вам нужно использовать компилятор, чтобы превратить код в исполняемый файл, прежде чем вы сможете его запустить. Код записывается в один или несколько текстовых файлов, которые вы можете открывать, читать и редактировать в любом текстовом редакторе, таком как Блокнот в Windows, TextEdit на Mac и gedit в Linux. Исполняемый файл - это то, что компьютер может запускать (выполнять). Компилятор проверяет код на наличие ошибок и, если он кажется безошибочным, создает исполняемый файл.
Прежде чем мы посмотрим, что входит в код C, давайте удостоверимся, что мы можем найти и использовать компилятор C. Если вы используете Mac OS X и большинство дистрибутивов Linux (например, Ubuntu), вы можете добавить компилятор C на свой компьютер, если вы установите программное обеспечение инструментов разработки для этой конкретной ОС. Эти бесплатные компиляторы C представляют собой инструменты командной строки, что означает, что вы обычно запускаете их из командной строки в окне терминала. Команда для запуска одного из этих компиляторов C - это «cc» или «gcc» плюс некоторые параметры и аргументы командной строки, которые другими словами вводятся после команды перед нажатием Enter.
Если вы используете Microsoft Windows или предпочитаете использовать графический пользовательский интерфейс, а не командную строку, вы можете установить интегрированную среду разработки (IDE) для программирования на C. IDE - это единый интерфейс, в котором вы можете написать свой код, скомпилировать его, протестировать и быстро найти и исправить ошибки. Для Windows вы можете приобрести программное обеспечение Microsoft Visual C ++, среду IDE для программирования на C и C ++. Другой популярной IDE является Eclipse, бесплатная IDE на основе Java, работающая в Windows, Mac и Linux и имеющая расширения для компиляции C и многих других языков программирования.
Для C, как и для других языков программирования, очень важна версия используемого вами компилятора. Вы всегда хотите использовать версию компилятора C, которая новее или новее, чем версия языка C, которую вы используете в своей программе. Если вы используете IDE, обязательно измените настройки, чтобы убедиться, что IDE использует вашу целевую версию C для программы, над которой вы работаете. Если вы находитесь в командной строке, вы можете добавить аргумент командной строки для изменения версии, как в следующей команде:
gcc –std c99 –o myprogram.exe myprogram.c
В приведенной выше команде «gcc» - это вызов для запуска компилятора, а все остальное - параметр или аргумент командной строки. Был добавлен параметр «-std», за которым следует «c99», чтобы указать компилятору использовать стандартную версию C C99 во время компиляции. Был добавлен параметр «-o», за которым следует «myprogram.exe», чтобы запросить имя исполняемого файла, выходного файла компилятора, myprogram.exe. Без «-o» исполняемый файл автоматически получает имя a.out. Последний аргумент «myprogram.c» указывает текстовый файл с кодом C для компиляции. Короче говоря, эта команда говорит: «Эй, gcc, скомпилируйте myprogram.c, используя стандарт программирования C99 C, и поместите результаты в файл с именем myprogram.exe».Просмотрите в Интернете полный список параметров, которые вы можете использовать с конкретным компилятором, будь то gcc или что-то еще.
Установив компилятор, вы готовы программировать на C. Давайте начнем с рассмотрения базовой структуры одной из простейших программ на языке C, которые вы могли бы написать.
Простейшая программа на C
Давайте посмотрим на простую программу C и воспользуемся ею для понимания основ C и процесса компиляции C. Если у вас есть собственный компьютер с установленным компилятором C, как описано ранее, вы можете создать текстовый файл с именем sample.c и использовать его, чтобы следить за тем, как мы пошагово рассмотрим этот пример. Обратите внимание: если вы оставите .c в имени файла или если ваш редактор добавит .txt к имени, вы, вероятно, получите какую-то ошибку при его компиляции.
Вот наша примерная программа:
/ * Пример программы * /
#включать
int main ()
{
printf ("Это результат моей первой программы! \ n");
возврат 0;
}
При компиляции и выполнении эта программа дает компьютеру команду распечатать строку "Это результат моей первой программы!" а потом остановись. Вы не можете найти ничего проще! Теперь давайте посмотрим, что делает каждая строка:
Строка 1 - это один из способов написать комментарии на C между / * и * / в одной или нескольких строках.
Строка 2 - Команда #include указывает компилятору искать другие источники существующего кода C, особенно библиотеки, которые представляют собой файлы, содержащие общие инструкции многократного использования. Ссылки на стандартную библиотеку C с функциями для получения ввода от пользователя и для вывода вывода на экран. Позже мы более внимательно рассмотрим библиотеки.
Строка 3 - это первая строка определения функции. Каждая программа на C имеет по крайней мере одну функцию или блок кода, представляющий что-то, что компьютер должен делать при запуске программы. Функция выполняет свою задачу, а затем создает побочный продукт, называемый возвращаемым значением, который может использоваться другими функциями. Как минимум, в программе есть функция с именем main, подобная показанной здесь, с возвращаемым значением с типом данных int, что означает целое число. Когда мы рассмотрим функции позже, вы увидите, что означают пустые круглые скобки.
Строки 4 и 7 - Инструкции внутри функции заключены в фигурные скобки. Некоторые программисты начинают и заканчивают заключенный в фигурные скобки блок на отдельных строках, как показано здесь. Другие помещают открывающую скобку ({) в конец первой строки определения функции. Хотя строки кода в программе не нужно набирать на отдельных строках, программисты обычно помещают каждую инструкцию в отдельную строку с отступом с пробелами, чтобы код было легче читать и редактировать позже.
Строка 5 - это вызов функции с именем printf. Эта функция закодирована в библиотеке stdio.h, включенной в строку 1, поэтому вам не нужно писать ее самостоятельно. Этот вызов printf сообщает ему, что выводить на экран. Однако \ n в конце в кавычках не печатается; это escape-последовательность, которая инструктирует printf переместить курсор на следующую строку на экране. Кроме того, как видите, каждая строка в функции должна заканчиваться точкой с запятой.
Строка 6 - Каждая функция, возвращающая значение, должна включать такой оператор возврата. В C функция main всегда должна иметь целочисленный тип возвращаемого значения, даже если она не используется в программе. Обратите внимание, что когда вы запускаете программу на C, вы, по сути, выполняете ее основную функцию. Итак, когда вы тестируете программу, вы можете указать компьютеру показать значение, возвращаемое при запуске программы. Возвращаемое значение 0 является предпочтительным, поскольку программисты обычно ищут это значение при тестировании, чтобы подтвердить успешное выполнение программы.
Когда вы будете готовы протестировать свою программу, сохраните файл, скомпилируйте и запустите программу. Если вы используете компилятор gcc в командной строке и программа находится в файле с именем sample.c, вы можете скомпилировать ее с помощью следующей команды:
gcc -o sample.exe sample.c
Если в коде нет ошибок, после выполнения этой команды у вас должен быть файл с именем sample.exe в том же каталоге, что и sample.c. Самая распространенная ошибка - это синтаксическая ошибка, означающая, что вы что-то опечатали, например, оставив точку с запятой в конце строки или не закрывающие кавычки или круглые скобки. Если вам нужно внести изменения, откройте файл в текстовом редакторе, исправьте его, сохраните изменения и попробуйте снова выполнить команду компиляции.
Чтобы запустить программу sample.exe, введите следующую команду. Обратите внимание на ./, который заставляет компьютер искать в текущем каталоге исполняемый файл:
./sample.exe
Это основы кодирования и компиляции для C, хотя гораздо больше вы можете узнать о компиляции из других ресурсов программирования на C. Теперь давайте откроем коробку и посмотрим, какие части C есть для создания программ.
Общие концепции программирования на C
Давайте посмотрим, как применить на практике некоторые общие концепции программирования в вашем C-коде. Ниже приводится краткое изложение этих концепций:
Функции. Как указывалось ранее, функция - это блок кода, представляющий то, что компьютер должен делать при запуске программы. Некоторые языки называют эти структуры методами, хотя программисты на C обычно не используют этот термин. Ваша программа может определять несколько функций и вызывать эти функции из других функций. Позже мы более подробно рассмотрим структуру функций в C.
Переменные - когда вы запускаете программу, иногда вам нужна гибкость, чтобы запустить программу, не зная заранее, какие значения указаны. Как и другие языки программирования, C позволяет использовать переменные, когда вам нужна такая гибкость. Подобно переменным в алгебре, переменная в компьютерном программировании представляет собой заполнитель, который обозначает какое-то значение, которое вы не знаете или еще не нашли.
Типы данных - чтобы хранить данные в памяти во время работы вашей программы и знать, какие операции вы можете выполнять с этими данными, язык программирования, такой как C, определяет определенные типы данных, которые он распознает. Каждый тип данных в C имеет определенный размер, измеряемый в двоичных битах или байтах, и определенный набор правил о том, что представляют его биты. Вскоре мы увидим, насколько важно выбрать правильный тип данных для задачи, когда вы используете C.
Операции - в C вы можете выполнять арифметические операции (например, сложение) над числами и строковые операции (например, конкатенацию) над строками символов. C также имеет встроенные операции, специально разработанные для вещей, которые вы, возможно, захотите делать со своими данными. Когда мы проверяем типы данных в C, мы также кратко рассмотрим операции.
Циклы - одна из самых простых вещей, которые может захотеть сделать программист, - это повторить действие несколько раз в зависимости от определенных условий, возникающих во время работы программы. Блок кода, предназначенный для повторения на основе заданных условий, называется циклом, а язык C предоставляет следующие общие структуры цикла: while, do / while, for, continue / break и goto. C также включает общие условные выражения if / then / else и операторы switch / case.
Структуры данных. Когда в вашей программе много данных, которые нужно обработать, и вам нужно отсортировать или выполнить поиск по этим данным, вы, вероятно, будете использовать какую-то структуру данных. Структура данных - это структурированный способ представления нескольких фрагментов данных одного типа. Самая распространенная структура данных - это массив, который представляет собой просто индексированный список заданного размера. В C есть библиотеки для обработки некоторых общих структур данных, хотя вы всегда можете писать функции и создавать свои собственные структуры.
Операции препроцессора - иногда вам нужно дать компилятору некоторые инструкции о том, что делать с вашим кодом, прежде чем компилировать его в исполняемый файл. Эти операции включают в себя замену постоянных значений и включение кода из библиотек C (который вы видели в примере кода ранее).
C также требует от программистов работы с некоторыми концепциями, которые многие языки программирования упростили или автоматизировали. К ним относятся указатели, управление памятью и сборка мусора. На следующих страницах рассказывается о том, что важно знать об этих концепциях при программировании на C.
Этот краткий обзор концепций может показаться ошеломляющим, если вы еще не программист. Прежде чем перейти к подробному руководству по программированию на C, давайте рассмотрим основные концепции среди перечисленных выше, начиная с функций.
Функции в C
Большинство языков программирования позволяют создавать какие-либо функции. Функции позволяют разбивать длинную программу на именованные разделы, чтобы вы могли повторно использовать эти разделы во всей программе. Программисты для некоторых языков, особенно тех, которые используют методы объектно-ориентированного программирования, используют термин метод вместо функции .
Функции принимают параметры и возвращают результат. Блок кода, который составляет функцию, является ее определением. Ниже приводится базовая структура определения функции:
{
возвращаться
}
Как минимум, программа на C имеет одну функцию с именем main. Компилятор будет искать основную функцию в качестве отправной точки для программы, даже если основная функция вызывает другие функции внутри нее. Ниже приводится основное, что мы видели в простой программе на языке C, которую мы рассматривали ранее. Он имеет целочисленный тип возврата, не принимает параметров и имеет два оператора (инструкции внутри функции), один из которых является оператором возврата:
int main ()
{
printf ("Это результат моей первой программы! \ n");
возврат 0;
}
Функции, отличные от main, имеют определение и один или несколько вызовов функций. Вызов функции - это инструкция или часть инструкции внутри другой функции. При вызове функции указывается имя вызываемой функции, за которым следуют круглые скобки. Если функция имеет параметры, вызов функции должен включать соответствующие значения для соответствия этим параметрам. Эта дополнительная часть вызова функции называется передачей параметров функции.
Но что такое параметры? Параметр функции - это фрагмент данных определенного типа, который требуется функции для выполнения своей работы. Функции в C могут принимать неограниченное количество параметров, иногда называемых аргументами. Каждый параметр, добавляемый к определению функции, должен указывать две вещи: тип данных и имя переменной в функциональном блоке. Несколько параметров разделяются запятой. В следующей функции есть два параметра, оба целые:
интервал doubleAndAdd (интервал a, интервал b)
{
return ((2 * a) + (2 * b));
}
Далее, давайте продолжим рассмотрение функций, уменьшив масштаб, чтобы посмотреть, как они вписываются в большую программу C.
Функциональные прототипы
В C вы можете добавить определение функции в любом месте программы (кроме другой функции). Единственное условие - вы должны заранее сообщить компилятору, что функция существует где-то позже в коде. Вы сделаете это с помощью прототипа функции в начале программы. Прототип - это утверждение, похожее на первую строку определения. В C вам не нужно указывать имена параметров в прототипе, только типы данных. Вот как будет выглядеть прототип функции для функции doubleAndAdd:
интервал doubleAndAdd (интервал, интервал);
Представьте себе прототипы функций как упаковочный лист для вашей программы. Компилятор распакует и соберет вашу программу так же, как вы могли бы распаковать и собрать новую книжную полку. Упаковочный лист поможет вам убедиться, что у вас есть все необходимые детали в коробке, прежде чем вы начнете собирать книжную полку. Компилятор использует прототипы функций таким же образом перед началом сборки вашей программы.
Если вы следуете программе sample.c, которую мы рассматривали ранее, откройте и отредактируйте файл, чтобы добавить прототип функции, определение функции и вызов функции для функции doubleAndAdd, показанной здесь. Затем скомпилируйте и запустите вашу программу, как раньше, чтобы увидеть, как работает новый код. Вы можете использовать следующий код в качестве руководства, чтобы попробовать:
#включать
интервал doubleAndAdd (интервал, интервал);
int main ()
{
printf ("Это результат моей первой программы! \ n");
printf ("Если вы удвоите, то сложите 2 и 3, результат:% d \ n", doubleAndAdd (2,3));
возврат 0;
}
интервал doubleAndAdd (интервал a, интервал b)
{
return ((2 * a) + (2 * b));
}
До сих пор мы рассматривали некоторые основные структурные элементы в программе на языке C. Теперь давайте посмотрим, с какими типами данных вы можете работать в программе на языке C и какие операции вы можете выполнять с этими данными.
Объявления функций
В C вы, вероятно, услышите термин «объявление функции» больше, чем «прототип функции», особенно среди старых программистов на C. Однако в этой статье мы используем термин «прототип функции», потому что он имеет важное различие. Первоначально объявление функции не требовало каких-либо параметров, поэтому достаточно было возвращаемого типа, имени функции и пары пустых скобок. Однако прототип функции дает компилятору важную дополнительную информацию, включая количество и типы данных параметров, которые он будет вызывать. Прототипы стали передовой практикой среди программистов сегодня на C и других языках программирования.
Типы данных и операции в C
С точки зрения вашего компьютера, данные - это не что иное, как последовательность единиц и нулей, представляющих включенное и выключенное состояния для электронных битов на вашем жестком диске, в процессоре или в памяти вашего компьютера. Программное обеспечение, которое вы запускаете на компьютере, определяет, как понимать эти миллиарды двоичных цифр. C - один из немногих языков высокого уровня, которые могут легко манипулировать данными на битовом уровне в дополнение к интерпретации данных на основе заданного типа данных.
Тип данных - это небольшой набор правил, указывающих, как разобраться в последовательности битов. Тип данных имеет определенный размер плюс собственный способ выполнения операций (таких как сложение и умножение) с данными этого типа. В C размер типа данных зависит от используемого вами процессора. Например, в C99 часть данных целочисленного типа данных (int) имеет длину 16 бит в 16-битном процессоре, а для 32-битных и 64-битных процессоров - 32 бита.
Еще одна важная вещь, которую должны знать программисты C, - это то, как язык обрабатывает подписанные и неподписанные типы данных. Знаковый тип означает, что один из его битов зарезервирован в качестве индикатора положительного или отрицательного числа. Таким образом, в то время как int без знака в 16-битной системе может обрабатывать числа от 0 до 65 535, авторизованный в той же системе может обрабатывать числа от -32 768 до 32 767. Если операция заставляет переменную int выйти за пределы своего диапазона, программист должен обработать переполнение с помощью дополнительного кода.
Учитывая эти ограничения и специфические особенности системы в типах данных и операциях C, программисты на C должны выбирать свои типы данных в зависимости от потребностей своих программ. Некоторые из типов данных, которые они могут выбрать, являются примитивными типами данных в C, то есть теми, которые встроены в язык программирования C. Обратитесь к своему любимому руководству по программированию на C, чтобы получить полный список типов данных в C и важную информацию о том, как преобразовать данные из одного типа в другой.
Программисты на C могут также создавать структуры данных, которые объединяют примитивные типы данных и набор функций, которые определяют, как данные могут быть организованы и ими можно управлять. Хотя использование структур данных является сложной темой программирования и выходит за рамки этой статьи, мы рассмотрим одну из наиболее распространенных структур: массивы. Массив - это виртуальный список, содержащий фрагменты данных одного типа. Размер массива нельзя изменить, но его содержимое можно скопировать в другие массивы большего или меньшего размера.
Хотя программисты часто используют массивы чисел, символьные массивы, называемые строками, обладают наиболее уникальными особенностями. Строка позволяет вам сохранить то, что вы могли бы сказать (например, «привет»), в серию символов, которые ваша программа на C может прочитать от пользователя или распечатать на экране. Управление строками имеет такой уникальный набор операций, что у него есть собственная выделенная библиотека C (string.h) с вашими типичными строковыми функциями.
Встроенные операции в C - это типичные операции, которые вы найдете в большинстве языков программирования. Когда вы объединяете несколько операций в один оператор, убедитесь, что вы знаете приоритет оператора или порядок, в котором программа будет выполнять каждую операцию в математическом выражении. Например, (2 + 5) * 3 равно 21, а 2 + 5 * 3 равно 17, потому что C будет выполнять умножение перед сложением, если нет круглых скобок, указывающих на обратное.
Если вы изучаете C, сделайте своим приоритетом ознакомление со всеми его примитивными типами данных и операциями, а также приоритетом операций в одном и том же выражении. Также поэкспериментируйте с различными операциями с переменными и числами разных типов данных.
На этом этапе вы прикоснулись к некоторым важным основам C. Однако теперь давайте посмотрим, как C позволяет вам писать программы, не начиная каждый раз с нуля.
Не начинайте с нуля, используйте библиотеки
Библиотеки очень важны в C, потому что язык C поддерживает только самые основные функции, которые ему нужны. Например, C не содержит функций ввода-вывода (I / O) для чтения с клавиатуры и записи на экран. Все, что выходит за рамки основ, должно быть написано программистом. Если фрагмент кода полезен для нескольких разных программ, его часто помещают в библиотеку, чтобы его можно было легко использовать повторно.
В нашем обсуждении C до сих пор мы уже видели одну библиотеку, стандартную библиотеку ввода-вывода (stdio). Строка #include в начале программы инструктирует компилятор C загрузить библиотеку из заголовочного файла с именем stdio.h. Сопровождающие C включают стандартные библиотеки C для ввода-вывода, математических функций, управления временем и общих операций с определенными структурами данных, такими как строка символов. Поищите в Интернете или в своем любимом руководстве по программированию на C информацию о стандартной библиотеке C89, а также обновлениях и дополнениях в C99.
Вы тоже можете писать библиотеки C. Таким образом вы можете разделить свою программу на повторно используемые модули. Этот модульный подход не только упрощает включение одного и того же кода в несколько программ, но также позволяет создавать более короткие программные файлы, которые легче читать, тестировать и отлаживать.
Чтобы использовать функции в файле заголовка, добавьте для него строку #include в начале своей программы. Для стандартных библиотек поместите имя соответствующего файла заголовка библиотеки между знаками «больше» и «меньше» (). Для библиотек, которые вы создаете сами, поместите имя файла в двойные кавычки. В отличие от операторов в других частях вашей программы C, вам не нужно ставить точку с запятой в конце каждой строки. Следующие шоу включают по одной библиотеки каждого типа:
#включать
#include "mylib.h"
Исчерпывающий исходный код программирования C должен содержать инструкции, необходимые для написания собственных библиотек на C. Определения функций, которые вы напишете, ничем не отличаются, находятся ли они в библиотеке или в вашей основной программе. Разница в том, что вы скомпилируете их отдельно во что-то, что называется объектным файлом (с именем, заканчивающимся на .o), и вы создадите второй файл, называемый файлом заголовка (с именем, заканчивающимся на .h), который содержит прототипы функций, соответствующие каждой функции в библиотеке. Это файл заголовка, на который вы будете ссылаться в строке #include в каждой основной программе, использующей вашу библиотеку, и вы будете включать объектный файл в качестве аргумента в команду компилятора каждый раз, когда компилируете эту программу.
Возможности C, которые мы исследовали до сих пор, типичны и для других языков программирования. Однако дальше мы поговорим о том, как C управляет памятью вашего компьютера.
Некоторые указатели на указатели в C
Когда ваша программа на C загружается в память (обычно в оперативную память или ОЗУ на вашем компьютере), каждая часть программы связана с адресом в памяти. Сюда входят переменные, которые вы используете для хранения определенных данных. Каждый раз, когда ваша программа вызывает функцию, она загружает эту функцию и все связанные с ней данные в память на время, достаточное для запуска этой функции и возврата значения. Если вы передаете параметры функции, C автоматически делает копию значения для использования в функции.
Тем не менее, иногда, когда вы запускаете функцию, вам нужно внести постоянные изменения в данные в их исходной ячейке памяти. Если C создает копию данных для использования в функции, исходные данные остаются неизменными. Если вы хотите изменить эти исходные данные, вы должны передать указатель на его адрес в памяти (передать по ссылке) вместо того, чтобы передавать его значение функции (передать по значению).
Указатели используются в C повсюду, поэтому, если вы хотите полностью использовать язык C, вы должны хорошо разбираться в указателях. Указатель - это переменная, как и другие переменные, но его цель - сохранить адрес памяти некоторых других данных. Указатель также имеет тип данных, поэтому он знает, как распознавать биты по этому адресу памяти.
Когда вы смотрите на две переменные бок о бок в коде C, вы не всегда можете распознать указатель. Это может быть проблемой даже для самых опытных программистов на C. Однако, когда вы впервые создаете указатель, это более очевидно, потому что перед именем переменной должна стоять звездочка. Это известно как оператор косвенного обращения в C. Следующий пример кода создает целое число i и указатель на целое число p:
int i;
int * p;
В настоящее время ни i, ни p не присвоено никакого значения. Затем давайте присвоим значение i, а затем присвоим p, чтобы он указывал на адрес i.
я = 3;
р = & я;
Здесь вы можете увидеть амперсанд (&), используемый в качестве оператора адреса непосредственно перед i, что означает «адрес i». Вам не нужно знать, что это за адрес, чтобы выполнить задание. Это хорошо, потому что каждый раз, когда вы запускаете программу, скорее всего, все будет по-другому! Вместо этого оператор адреса будет определять адрес, связанный с этой переменной, во время работы программы. Без оператора адреса присвоение p = i буквально присвоило бы p адрес памяти 3, а не адрес памяти переменной i.
Затем давайте посмотрим, как можно использовать указатели в коде C и к каким проблемам вы должны быть готовы.
Правильное использование указателей в C
Получив указатель, вы можете использовать его вместо переменной того же типа данных в операциях и вызовах функций. В следующем примере указатель на i используется вместо i в более крупной операции. Звездочка, используемая с p (* p), указывает, что операция должна использовать значение, которое p указывает на этот адрес памяти, а не сам адрес памяти:
int b;
б = * р + 2;
Без указателей в вашей программе на языке C практически невозможно разделить задачи на функции вне main. Чтобы проиллюстрировать это, представьте, что вы создали в main переменную с именем h, которая хранит рост пользователя с точностью до сантиметра. Вы также вызываете написанную вами функцию с именем setHeight, которая предлагает пользователю установить это значение высоты. Строки в вашей основной функции могут выглядеть примерно так:
int h;
setHeight (h); / * Здесь есть потенциальная проблема. * /
Этот вызов функции попытается передать значение h в setHeight. Однако, когда функция завершает работу, значение h не изменится, потому что функция использовала только ее копию, а затем отбросила ее, когда она завершила работу.
Если вы хотите изменить сам h, вы должны сначала убедиться, что функция может принимать указатель на существующее значение, а не на новую копию значения. Таким образом, первая строка setHeight будет использовать указатель вместо значения в качестве параметра (обратите внимание на оператор косвенного обращения):
setHeight (int * height) {/ * Здесь находятся операторы функций * /}
Затем у вас есть два варианта вызова setHeight. Первый - использовать адресный оператор для h в качестве переданного параметра (& h). Другой - создать отдельный указатель на h и передать его вместо него. Ниже показаны оба варианта:
setHeight (& h); / * Передаем адрес h функции * /
int * p;
p = & h;
setHeight (p); / * Передаем в функцию отдельный указатель на адрес h * /
Второй вариант раскрывает общую проблему при использовании указателей. Проблема заключается в наличии нескольких указателей на одно и то же значение. Это означает, что любое изменение этого значения влияет на все его указатели сразу. Это может быть хорошо или плохо, в зависимости от того, чего вы пытаетесь достичь в своей программе. Опять же, освоение использования указателей - важный ключ к овладению программированием на C. Практикуйтесь с указателями как можно больше, чтобы быть готовым к решению этих проблем.
Возможности C, которые мы исследовали до сих пор, типичны и для других языков программирования. Однако затем мы рассмотрим требования C к тщательному управлению памятью.
Важность управления памятью в C
Одна из вещей, которая делает C таким универсальным языком, заключается в том, что программист может масштабировать программу для работы с очень небольшим объемом памяти. Когда C был впервые написан, это было важной особенностью, потому что компьютеры были не такими мощными, как сегодня. В связи с текущим спросом на небольшую электронику, от мобильных телефонов до крошечных медицинских устройств, возобновился интерес к сохранению небольших требований к памяти для некоторого программного обеспечения. C - это язык, к которому обращаются большинство программистов, которым нужен большой контроль над использованием памяти.
Чтобы лучше понять важность управления памятью, рассмотрим, как программа использует память. Когда вы впервые запускаете программу, она загружается в память вашего компьютера и начинает выполняться, отправляя и получая инструкции от процессора компьютера. Когда программе необходимо запустить определенную функцию, она загружает эту функцию в еще одну часть памяти на время ее выполнения, а затем покидает эту память, когда функция завершается. Кроме того, каждый новый фрагмент данных, используемый в основной программе, занимает память на время выполнения программы.
Если вам нужен больший контроль над всем этим, вам нужно динамическое распределение памяти. C поддерживает динамическое выделение памяти, то есть возможность резервировать память по мере необходимости и освобождать эту память, как только вы закончите ее использовать. Многие языки программирования имеют автоматическое выделение памяти и сборку мусора, которые обрабатывают эти задачи управления памятью. Однако C позволяет (а в некоторых случаях требует) явным образом указывать выделение памяти с помощью следующих ключевых функций из стандартной библиотеки C:
- malloc - сокращение от выделения памяти, malloc используется для резервирования блока памяти заданного размера для хранения определенного типа данных, которые необходимо обработать вашей программе. Когда вы используете malloc, вы создаете указатель на выделенную память. Это не обязательно для отдельного фрагмента данных, такого как одно целое число, которое выделяется, как только вы его впервые объявляете (как в int i). Однако это важная часть создания и управления структурами данных, такими как массивы. Альтернативные варианты выделения памяти в C - это calloc , которая также очищает память, когда она зарезервирована, и realloc , которая изменяет размер ранее зарезервированной памяти.
- free - используйте команду free, чтобы заставить вашу программу освободить память, ранее назначенную данному указателю.
Лучшая практика при использовании malloc и free - освободить все, что вы выделяете. Всякий раз, когда вы выделяете что-либо, даже во временной функции, оно остается в памяти до тех пор, пока операционная система не очистит пространство. Однако, чтобы гарантировать, что память свободна и готова к немедленному использованию, вы должны освободить ее до выхода из текущей функции. Такое управление памятью означает, что вы можете свести к минимуму объем памяти, занимаемый вашей программой, и избежать утечек памяти. Утечка памяти - это недостаток программы, при котором она продолжает использовать все больше и больше памяти до тех пор, пока ее не остается выделить, что приводит к зависанию или сбою программы. С другой стороны, не стоит так беспокоиться об освобождении памяти, чтобы освободить и, таким образом, потерять то, что вам понадобится позже в той же функции.
В этой статье вы узнали некоторые из основных структур и основных концепций языка программирования C. Мы изучили его историю, общие характеристики с другими языками программирования и важные особенности, которые делают его уникальным и универсальным вариантом для программирования. Перейдите на следующую страницу, чтобы получить больше информации, в том числе некоторые руководства по программированию, которые проведут вас дальше на пути к C.
Еще больше информации
Статьи по Теме
- Основы программирования на C
- Как работает Java
- Как работает логическая логика
- Как работает PERL
- Как работает BIOS
- Как работает скриптинг CGI
- Как работают биты и байты
Больше отличных ссылок
- C Programming.com Учебник
- Программирование на C в Викиучебнике
- Коллекция компиляторов GNU (GCC)
- Программное обеспечение интегрированной среды разработки Eclipse
Источники
- Керниган, Брайан В. и Ричи, Деннис М. «Язык программирования C, второе издание». Прентис Холл. 1988 г.
- Кинг, К.Н. «Программирование на языке C: современный подход, второе издание». WW Norton & Company, Inc. 2008 г.