C (език за програмиране)

С програмен език (произнася се „си“ в оригинал на английски, защото е на латиница) е разработен за програмиране на софтуер и операционни системи език. Той има предназначение за стабилна работа с процесора и хардиска, за стабилно стартиране и работа на програмите, както и на цели операционни системи, с опции за мултитаскинг от страна на потребителя, тоест този вид софтуер, писан на С е толкова стабилен, че позволява потребителя да работи с него, докато прави и други неща. С дава възможност за улесняване на работата на компютъра и програмата не само с харддиска и процесора, основни входно-изходни устройства като клавиатура и монитор, но и други като мрежови входове и т.н. Тоест C e направен така, че дадената програма да е приложима за съответния тип компютър и конфигурация, но също така да работи при включен интернет или дори да работи с Интернет при запазване на стабилността на системата. 

С е език за програмиране от високо и в някои програмистки среди средно ниво с обширно и също общо предназначение. Програмистите имат повече контрол върху хардуера и програмите, написани на него, обикновено работят по-бързо от тези, написани на езици от високо ниво на портативност. Затова C е подходящ за създаване както на операционни системи, така и на софтуер, предназначен за тях, и по-рядко и дори много рядко за приложения.

Според някои непрофесионални програмисти и дивелопъри, преносимостта на кода (която е винаги налична, при положение че една програма може да се напише на всеки език, или за по-бързо пренапише), съчетана с неговата ефективност (каквато може да има само рядко при Java, и то само при работа на едно Java приложение при работещи останали софтуерни програми на C), прави езика "доста популярен". Той получава голямо разпространение, като за него съществуват компилатори за многобройни операционни системи и компютърни платформи. Много от днешните операционни системи са написани главно на C. Популярните езици C++ и Objective-C са разширения на езика С.

Код, написан на С, може много лесно да се използва на различни платформи. За езика са разработени няколко стандарта – KNR, ANSI C и C99.

История

Началото 
Първоначално C се разработва в AT&T Bell Labs между 1969 и 1973 г, като най-креативният период е през 1972, която се приема и за годината на създаването му.

Според други източници разработчик е Денис Ричи в периода 1969 – 1973 г. Разработката на езика е тясно свързана с операционната система UNIX, чието ядро впоследствие бива пренаписано на езика C.

Произходът на C е тясно свързано с разработването на операционната система UNIX, първоначалното написана на асемблер за компютъра PDP-7 от Ричи и Томпсън, които включват няколко идеи от техни колеги. За да обогати възможностите на системата, Томпсън създава системния език B, който представлява опростена версия на езика BCPL. По-късно UNIX се пренаписва за новата машина PDP-11, но заради някои недостатъци на езика B, поради които не може да се използва пълния потенциал на PDP-11, Денис Ричи решава да създаде езика C. Качествата на C като абстрактност и преносимост бързо го правят популярен и през 1973 г. операционната система UNIX е пренаписана на този език което значително улеснява пренасянето ѝ на други машини.

K&R C 
През 1978 г. Браян Керниган и Денис Ричи написват книгата The C Programming Language. Тази книга (наричана за кратко K&R) е първата по-формална спецификация на езика и впоследствие версията на C описана в книгата започва да се нарича K&R C. Второто издание на книгата описва създаденият по-късно формален стандарт на езика ANSI C. Но дори и след излизането на ANSI C, много програмисти предпочитат да ограничават кода си в рамките на K&R C за максимална преносимост на кода, тъй като много от старите компилатори разбирали само K&R C а внимателно написан K&R C код може да бъде и съвместим с ANSI C.

ANSI C и ISO C 

Изключителната популярност на езика довежда до разработването на компилатори и разновидности на езика с различни разширения за множество компютри. За да подобри преносимостта на кода и за да осъвремени съществуващия стандарт, през 1983 г. Американският национален институт по стандартите (ANSI) сформира работна група имаща за цел да създаде формално описание на C. През 1989 г. стандартът е завършен и ратифициран под името ANSI X3.159 – 1989 „Programming Language C“. Версията на езика описана в документа често се нарича ANSI C или C89.

През 1990 г. стандартът ANSI C се възприема и от Международната организация по стандартизация (ISO) под името ISO/IEC 9899:1990, накратко наричан C90. Тъй като съдържателно стандартите са едни и същи (различават се само по оформлението) C89 и C90 се отнася до един и същи език.

C99 
C99 е нов стандарт на езика, утвърден през 1999 от ISO/IEC, добавящ някои важни и възможности, между които са:
 Inline функции
 Премахване ограничението за деклариране на променливи само в началото на блок
 Нови типове данни, включващи long long int, boolean и др.
 Променлива дължина на масивите
 Поддръжка на едноредови коментари //, като в някои други езици за програмиране
 Нови библиотечни функции
 Нови заглавни файлове, като stdbool.h и inttypes.h
 Подобрена поддръжка на IEEE floating point
 Добавяне на нови ключови думи, като restrict

Характеристика 
Програмите написани на C представляват съвкупност от файлове с изходен код. Чрез компилация всеки файл се превежда до машинно зависим обектен код за определена архитектура, а свързващ редактор обединява тези относително независими обектни файлове в цялостен изпълним файл.

C е структурен език, използващ конструкции като условни преходи (if.. else), цикли (while, for) и абстрахиране на кода чрез функции изпълняващи относително самостоятелни задачи.

Някои от най-важните характеристики на езика са:
 Слабо типизиран (weak typing) – Позволява автоматично преобразуване между някои типове данни.
 Статично типизиран (static typing) – Типовете на данните се определят по време на компилирането.
 Позволява работа с паметта на ниско ниво – поддържа указатели към променливи, указатели към функции и адресна аритметика.
 Използва сравнително малък набор от ключови думи, като за сметка на това използва сравнително голямо количество оператори.
 Всеки израз връща стойност – дори присвояването, което прави възможно множествено присвояване от вида x=y=5. Стойностите обаче могат да бъдат игнорирани когато не са нужни.
 Параметрите към функциите винаги се предават по стойност. Така достъпът до външна променлива чрез параметър може да стане само индиректно чрез подаване на указател.
 Изобилстваща употреба на предпроцесор за създаване на макро дефиниции, включване на файлове и условно компилиране.

Синтаксис

Основни типове данни 
Типовете данни зависят от конкретния компилатор който се използва. Данните показани по-долу са примерни за 32bit Intel съвместими процесори.

Запазени думи 
Стандартът ANSI C определя 32 ключови думи, които не могат да се използват в имената на функции или променливи. Много компилатори на С добавят други ключови думи. В С главните и малките букви се различават (int, Int и INT са различни).

Запазени думи:

auto, _Bool, break, case, char, _Complex, const, continue, default, do, double, else, enum, extern, float, for, goto, if, _Imaginary, inline, int, long, register, restrict, return, short, signed, sizeof, static, struct, switch, typedef, union, unsigned, void, volatile, while

Примерът „Здравей, свят!“ 
Следва класическата примерна програма, извеждаща на екрана текста Hello, World! („Здравей, свят!“):

 #include <stdio.h>

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

Първият ред представлява директива (#include) към предпроцесора за включване на външен файл (stdio.h) който съдържа описанията на някои стандартни функции за вход и изход на данни. В случая е нужен за да може компилаторът да намери описанието на функцията за форматиран изход printf. Триъгълните скоби указват да се търси в каталога със стандартни заглавни файлове.

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

Във фигурните скоби е поместено тялото на функцията което ще се изпълни. Започва с извикване на функция от стандартната библиотека на C – printf, която в случая приема единствен параметър – указател към низ от символи. Двойните кавички създават анонимен низ (низова константа) от символите заградени в тях в паметта и връща указател към него. Нарича се анонимен защото не е присвоен на променлива и съответно по-късно няма да можем да се обърнем към него чрез такава променлива. Комбинацията от символи \n се нарича управляваща последователност, защото символите ѝ не се възприемат буквално от компилатора. Управляващи последователности се използват за вмъкване на символи които или не бихме могли директно да въведем или биха нарушили синтаксиса на програмата. В случая \n означава символ за нов ред; ако просто бяхме въвели истински, буквален символ за нов ред, компилаторът щеше да даде съобщение за грешка тъй като синтактичните правила изискват изразите да заемат един-единствен ред. Символът ; поставя края на израза който е основния градивен блок на програмите. Изразът return 0; прекратява изпълнението на функцията и връща целочислената стойност нула. Често функциите, освен ако нулата не е валидна резултантна стойност на задачата изпълнявана от функцията, връщат нула за да сигнализират че не е възникнал проблем при изпълнението им. Но това е различно за всяка функция и за смисъла на връщаните стойности програмистът трябва да се допита до документацията.

Основи на файловата система 
Както повечето езици за програмиране, така и C си има своя конвенция за вход-изход на файлове. Основните понятия свързани с работата с файлове са: поток и файл. Файловата система на езика предоставя на програмиста постоянен интерфейс, независещ от използваното устройство, именно този интерфейс се нарича поток. Или по друг начин казано потокът представлява логически интерфейс към файла. Файлът от своя страна е мястото където потокът съхранява или чете (зависимост от операцията) данни.

Файловете биват два вида:
 текстов – при текстовите файлове има знаково преобразование, което ще рече, че може да има несъответствие между реалното съдържание и съдържанието на файла, защото знаците биват преобразувани от двоичен формат в ASCII знаци.
 ASCII представлява еднозначно съответствие между двоичен код и начина на изобразяване на даден знак. Това не е самото изобразяване на знаците (глифове), под глифове в компютърния свят се има предвид шрифтовете, ASCII кода просто „казва“ на дадения шрифт под някой_си_номер (ASCII код) се крие знакът някой_си_знак, а шрифтовете от своя страна визуализират конкретния знак на екрана.
 двоичен – при двоичните файлове няма никакво преобразование и съдържанието от/към файла е 1:1, а един двоичен файл съдържа само нули и единици, за разлика от текстовия файл където се съхраняват ASCII знаци, заедно с т.нар. контролни знаци (\n, \r, \t и др.)

Езикът съдържа различни вградени функции за работа с файлове, прототипите на някои от тях са:
 FILE * fopen (const char *filename, const char *mode);
 int fclose (FILE *stream);
 size_t fread (void *ptr, size_t size, size_t count, FILE *stream);
 size_t fwrite (const void *ptr, size_t size, size_t count, FILE *stream);
 int fgetc (FILE *stream);
 int fputc (int character, FILE *stream);
 int fprintf (FILE *stream, const char *format, ...);
 int fscanf (FILE *stream, const char *format, ...);

Отваряне на файл чрез fopen 
*FILE fp;
fp=fopen(char *filename, char *mode);
*FILE fp – името на потока, чрез който се извършва връзката с файла, задължително трябва да бъде указател;char *filename – името на файла, достъпен за операционната система, подава се на функцията във вид на символен низ.
char *mode – един от следните режими за работа с файлове:

Ако отворим вече съществуващ файл в режим „w“/"wb" неговото съдържание ще бъде изтрито и ще се запише новата информация, докато ако отворим същият файл в режим „а“/"ab" новата информация ще се запише след края на старата.
Функцията връща: 
- указател към файла – ако е приключила успешно
- NULL (нулев указател) – ако е приключила неуспешно

Примерен код за създаване на файл, зададен като аргумент:
#include <stdio.h>
#include <stdlib.h> // exit()

int main(int argc, char *argv[])
{
	FILE *fp; /* файлов указател */

	/* проверка за валиден брой аргументи */
	if(argc>2) {
		printf("Too many arguments.");
		exit(1);
	} /* край на проверката */

	/* отваряне на файла за запис */
	if((fp=fopen(argv[1], "w"))==NULL) {
		printf("Cannot open file %s for writing", argv[1]);
		exit(1);
	}

	else printf("Okay, file %s is create", argv[1]);

	fclose(fp); /* затваряне на файла */

	return 0;
}

Източници

Допълнителна литература

Външни препратки 
 Основни елементи на езика C 
 Стандартни функции на езика C