Най-четените учебни материали
Най-новите учебни материали
***ДОСТЪП ДО САЙТА***
ДО МОМЕНТА НИ ПОСЕТИХА НАД 2 500 000 ПОТРЕБИТЕЛИ
БЕЗПЛАТНИТЕ УЧЕБНИ МАТЕРИАЛИ ПРИ НАС СА НАД 7 700
Ако сме Ви били полезни, моля да изпратите SMS с текст STG на номер 1092. Цената на SMS е 2,40 лв. с ДДС.
Вашият СМС ще допринесе за обогатяване съдържанието на сайта.
SMS Login
За да използвате ПЪЛНОТО съдържание на сайта изпратете SMS с текст STG на номер 1092 (обща стойност 2.40лв.)Лекции по C |
![]() |
![]() |
![]() |
Основни синтактични елементи на С 1.Константи а)целочислени константи-поддържа 3 бройни системи-10,8,16 Целочислените константи получават тип int или long в зависимост от стойността си. Осмичните и шестнайстичните константи получават тип int или long в зависимост от стойността си, но ако във водещия разряд попадне значеща цифра , то се преписва беззнаков int (unsigned) или long. Извън това подразбиране програмата може да управлява своите константи чрез суфикс. Вътрешното представяне е в допълнителен код. б)числени плаващи константи-записват се със или без експонента. Ако няма e константите трябва да включват десетична точка, иначе не е задължително. Началото на експоненциалната част се обузначава с буквата e (e,E). Може да се пропуска както цялата, така и дробната част, но не и двете едновременно Всички плаващи константи получават тип double , но програмиста може да управлява типа на константите чрез суфикс F,f (константите получават тип float-4 байта). Разликата е в заетата памет. IEEE 754-стандарт за предотвратяване на плаващите константи. Стандарта предлага 2 форми 2)експонентът е с излишък ЕМ=Eg+127 ЕМ=Eg+1023 Всички положителни експоненти започват с 1 във водещия бит, а всички отрицателни с 0. 3)1≤│M│<2 мантисата е едно цяло и нещо в)текстови данни (низове)-произволна последователност от символи заградени в двойни кавички. Низа може да включва ескеип последователноси. Всяка тектова константа има стойност с характер на адрес. Това е адреса на първия байт от паметта, където се съхранява текстовата данна г)символни данни-произволен символ заграден в единични кавички (апостоф) разрашено е използването на еск.последователност Всяка символна константа има 2 тълкувания: -данна с тип char и може да се появи, където е разрешена употребата на char данна -число съвпадащо с цифровата стойност на кода на символа и поради тази причина може да се изплзва в изрази, където е разрешено употребата на целочислени данни 2. Имена – последователност от букви и цифри започващи с буква (31 символа максимална дължина) ! Ключовите думи са резервирани и се пишат с малки букви! С поддържа класификация на имената т.е. имената се включват в групи, не е разрешено да има повторение на имената в една и съща група, но между групите е възможно повторение. По известни класове на имената са: - клас, който включва: имена на данни, имена на функции, формални параметри, константи на изброени данни, типове създадени чрез type def. - клас на имената на шаблони, дефинирани за структури, обединения и изброени данни. - класове на компонентите на структури и обединения (всяка структура образува отделен клас) - клас на етикетите 3. Коментари /* ........... */ - произволен текст // CR – коменат на един ред С работи само с горното, но в повечето реализации пидържа и двата типа. Структура и изпълнение на С-програма Програмата на С можe да бъде разположена в един или няколко файла. Всеки от файловете може да съдържа: - дефиниция на дании и функции - декларации на дании и функции - директиви на компилатора При структуриране на програмата на С програмиста се ръководи от едно правило – нито един от горните елементи не може да започва в един файл и да продължава в друг. Дефиниция - Програмния елемент, който създава данни към програмата или създава изпълнимата част на дадена фукция. Декларация - Програмния елемент, който прави описание на свойства на данните или описва начина, по който една функция може да бъде извикана за изпълнение. В групата файлове изграждаща програмата трябва да е включена една специална функция със стандартно име main – това е главната програма. От нея започва изпълнението на програмата. Тя може да извика други подпрограми, които след изпълнението си и връщат управлението. Програмата приключва след достигане на физическия край на main или по-рано ако логическия край не съвпада с физическия. Дефинициите и декларациите могат да бъдат разположени във файла на 2 места: - вън от всякакви функции (между функциите) – такава дефиниция/декларация се нарича дефиниция/декларация на външно ниво. - в тялото на някаква функция – в началото на тялото за езика С такава дефиниция/декларация се нарича дефиниция/декларация на вътрешно ниво; Вътрешното и външното ниво определят съществени характеристики свързани с сферата на активността на имената. Стандарнто активността на имената се управлява от две класически правила: - описанието на всяко име действа напред в текущия файл до края на функцията ако описанието е на вътрешно ниво или до края на файла ако описанието е на външно ниво. Ако описанието е на външно ниво, то действа и в телата на следващите функции освен ако същото име в тялото на функцията получи ново описание. Това локалко описание, което има сфера на действие тялото на функцията приоритетно прикрива изпреварва описанието на външно ниво. - Имената създадени в един файл могат да бъдат направени видими в друг файл с подходяша декларация. Ако декларацията е на вътрешно ниво то името ще бъде известно само в тялото на функцията, а ако е на външно ниво – до края на файла. Обвързването ня файловете в изпълнима програма може да се извърши по два начина, кото най-често се комбинират - чрез използване на input директиви – те се интерпретират от компилатора преди да започне същинската компилация и по същество представляват обединение на двата файла в един, тъй като компилатора замества input директивата с текста на файла. - с помощта на свързващ редактор всеки файл трябва да бъде самостоятелно компилиран. Дефиниране на данни. Деклариране на данни и функции.
[] [[=]],,,; Позицията клас памет клас памет за данните опредееля как се разпределя паметта. При декларация на функция с клас памет се указва, че израза е декларация, а самата дефиниция е другаде. В случай, че клас памет се пропусне свойствата на конструкцията произтичат от мястото на запис на вътрешно или външно ниво. Подразбирания клас памет за функции е extern. За данни значи, че израза е декларация, за функции изречението е декларация, ако отсъства тяло. Ако е налично тяло записът е излишен т.к. се подразбира. Static - за данни, преписва се статично разпределение на паметта. Такива данни са глобални данни и имат глобален интервал на живот -за функции- всички функции имат глобален интервал на живот, заова записа на static е излишен освен ако се цели защита на името в текущия файл.Всички static имена се защитават в текущия файл, не могат да бъдат направени известни чрез декларация в друг файл. В друг файл могат да се ползват за съвсем различни цели. Auto - може да бъде записано само на вътрешно ниво. Записът му е безмислен т.к. то се подразбира. ПАмет се задееля при актовиране на функцията и се освобождава при нейното дезактивиране. Register - еквивалентен на auto като в случай, че не може да се изпълни като auto предоставя заявки към компилатора за разпределение на памет в свръхоперативната памет, за да се ускори изчислителния процес. extern - за декларация static – само за защита Типов спецификатор – Ако се пропусне се подразбира int. Пропуска се при декларация на функции, ако типа на връщане е int. Ако дефинираме/декларираме данни типовия спецификатор може да определя: -типът на дефинираната/декларирана данна -ако се създава указателтипът на указваната данна -ако се прави описание на масив това е типа на компонентите на масива -ако се декларира футкция това е типът на връщаната стойност, а ако функцията връща указател –типа на указваната стойност -при дефиниране/декрариране на структура обединение с типвия спецификатор може да се опише архитектурата на тези данни. Декларатор – чрез него се задава името на данната, която получава описание или името на декларираната функция. Името може да бъде модифицирано: -префиксно със звезда и тогава описваната данна се превръща в указател, а декларираната функция връща указател към данна с тип определен от типовия спецификатор. -суфиксно може да се запишат средни скоби това означава, че декларира/дефинира масив -суфиксно с малки скоби-при декларация на функции. Разрешените декларатори са : │*││[[│[]│(,,,)│( ) │ () Декларатор, който съдържа повече от 1 модификатор се нарича комплексен. -* - декларира/дефинира се данна, която е указател -декларатор с константен израз-декларира/дефинира се масив, чийто брой елементи е зададен от константния израз. Достъп до елементите на масива може да се постигне чрез операция индексиране като индексиранито започво от нула!!!! С непознава 2,3 и повече мерни масиви. Всички масиви за С са едномерни. Компонентите на масива могат да бъдат сложни данни включително и масиви, и по този начин се създава илюзята за съществуването на 2-3 и повече мерни масиви. [ ] декларатор и средни скоби-частен случай на предходния и винаги може да се замести от предходния, но може да се укаже броя на елементите. Има ограничено проложение. Може да се използва в следните случаи: -ако се създаде масив, който непосредствено се инициализираброя елементи се определя от инициализиращите -ако се прави декларация на масив броя на елементите не е необходимо да се указва т.к. масива се създава на друго място -при описание на формални параметри броя не се указва той се определя от аргумента-в случай, че се прави описание на многомерен масив може да се пропусне само броя елементи по първи индекс (,,,)-иползва се само при деклариране на функции. Списъкът от типови имена задава типът на формалните параметри. Всяко типово име има следния синтаксис: [] Типовото име има за цел да определи типа на текущия формален параметър. Ако това може да се извърши без модификация, то се записва само типов спецификатор. Ако типа на формалния параметър трябва да се модифицира, то се записва и абстрактен декларатор, който представлява натрупване на модификатори без име. - ( ) – само при деклариране на функция. Има голяма разлика между тъкуването на този декларатор в С и С++. С++ - декларира функция без параметри, но се препоръчва да се запише специален типов спецификатор void. С – Този типов спецификатор означава, че програмиста не иска да сподели с компилатора характера на формалните параметри! Може да е декларация на функция без параметри или с произволен брой параметри. За С записването на void е просто добър стил. Като има void значи че няма параметри. - () – променя тълкуването на модификаторите ако това е наложително. Такава промяна в тълкуването може да се извърши в следствие на факта, че трите вида модификатори са знаци за операции, които имат приоритет. По-висок приоитет са малки средни скоби и те се тълкуват от ляво на дясно. Посоченият ред на изпълнение на модификаторите позволява да се извъши прочитане на т. нар. комплексни декларатори като се спазват следните правила: - спазва се приоритета на операциите - някои комбинации на скоби са забранени: * всяка функция не може да връща функция или масив и се състои от функции. * * пред име на функцията променя връщаната стойност в указател * * пред име на масив променя компонентите на масива в указатели * последен при четенето се прилага типовия спецификтор Допълнителни модификатори near, far, huge, cdecl, fortran, pascal near, far и huge – атавизъм – изостанали от 16 битовата реализация на ОС. huge – за данни по-големи от 16 бита. Останалите определят конвенцията за заместване на параметрите. Могат да се използват както при дефиниции така и при деклаации на функциите. Тези модификатори могат да се записва пред всеки декларатор като променят неговото тълкуване. Допуска се и тълкуване на такива модификатори. Инициализатори Могат да бъдат записани само за данни, които не се декларират, се дефинират. С тях се определя начална (инициализираща) стойност на данната. Има 2 форми на инициалшизатора. |{,,,} агрегат Допуска се агрегиране или факторизиране на инициализацията. Данните със статично разпределени на памет (дефинирани на външно ниво или static данни на върешно ниво) трябва да се инициализират само със статични изрази. Ако не се извъши инициализация може да се разчита, че данната се нулира. Ако е предвидена инициализация тя се извършва еднократно при стартиране на програмата. Данните дефинирани на вътрешно ниво могат да се инициализират с произволни изрази, в които могат да участват и данни получени по време на работа на програмата. Инициализацията се извършва при всеки вход във функцията, която съдържа дефиницията. Сложни данни на вътрешно ниво не могат да се инициализират, но може ако са static. Ако се зададе по-малък брой инициализиращи стойности останалите елменти на сложни данни се чистят, ако се зададе по-голям брой се сигнализира за грешка. Изброяването на инициализиращи стойности трябва да следва реда на разполагане на елементите на сложна данна в паметта, тъй като не е разрешено използване на имена. При инициализиране на обединения се прави инициализажия само на първи елемент. Реда на инициалиация може да се наруши ако се използва влагане на агрегати, тъй като всеки агрегат обслужва една съставна част (сложна данна) на инициализираната данна. Масиви char могат да се инициализират чрез низови константи, ако се даде повече символи те се игнорират. Целочислени данни в С Два целочислени типа: int и char. И двата са знакови типове. Char е еднобайтов, а int е подразбран тип – char не е и трябва да се пише. Int може да се предифинира с два модификатора. {signed/unsigned} {short/long} int {signed/unsigned} char По този начин се избира знаково или беззнаково представяне; късо или дълго представяне. Знаковото представяне е подразбрано. Правило: Отношението int short long се определя от средата върху която се реализира езика. Ако основната дума е дълга дума, но съществува полудумова аритметика, то тогава int съвпада с long и се реализира с дума, а short е полудума. Ако няма полудумова аритметика short и int съвпадат с думата а long се реализира с двойна дума. Изброени данни Изброените данни в С по същество са целочислени данни, множеството стойности също се задава с имена и по аналогичен на Pascal начин съществува вътрешна номерация, която започва от 0. Всяка поява на изброена данна в предеите на израз се тълкува като поява на вътрешен номер, поради което изброените данни се причисляват към целочислените. Типовия спецификатор е следния (т.с) enum []{,,,} enum шаблон При пълния т.с. се изброява и множеството от стойности на изброената данна. То може да получи име (име на шаблона) В зоната на видимост на това име може да се употребява съкратения т.с. , като става позоваване на шаблона. Всяка изброена данна е еквивалентна на int. Това може да се забрани чрез различни флагове на компилатора => не може да се присвои 1000, а само от 0 до 3. Елементът може да има сложен вид: [=] Израза задава ново начало на броя за следващите константи на изброения тип Плаващи данни float (4 байта), double (8 байта), long double-10 байта Масиви и указатели 1.Масиви-името на масива може да се счита за данна с тип указател, тъй като масива не може да се мести по паметта – това е константа. Това е адреса на първия байт от паметта, който е разпределен за масива. За достъп до елементите на масива се използва така известната индекс опрация. [] - единият от 2та израза трябва да бъде с характер на адрес, а другия трябва да се изчислява до целочислена стойност. Израз1 е адресен израз. Индексната опрерация се изпълнява по следния алгоритъм: - изчислява се израз1 - изчислява се израз2 и се умножава по дължината на елементите (компонентите на масива). - получените 2 стойности се събират и се получава адрес. От този момент индексната операция може да продължи по различен начин в зависимост от това дали се адресира сложна данна и дали индексирането е вдясно или ляво на операцията за присвояване. Ако се адресира скаларен елемент и сме вдясно от равенството се извършва автоматично косвено адресиране, прочита се адресираната даннна и това е резултата от операцията. Ако индексирането е вляво от равенството изчисления адрес е получател на данните, които са резултат на израза вдясно от равенството. Ако се адресира сложна данна без значение е дали операцията е вляво или вдясно от равенството, изчислителния адрес е резултат от операцията. (Ако е вдясно този резултат може да се ползва, той е операнд, ако е вляво не може да се ползва – сигнал за грешка). Данни указатели Над данна указател може да се извършва операция косвено адресиране *. То може да стои както вляво, така и вдясно на операцията за присвояване. Ако е вдясно се извършва прочитане на данните сочени от указателя, ако се сочи скаларна данна, иначе операцията е грешна. Ако е влявно от равенството адреса сочен от указателя е получател на данната. ± Тази цяла стойност трябва да се изчисли като се умножи по дължината на данните сочени от указателя. Получената стойност се прибавя към адреса сочен от указателя и това е резултат от операцията. Данните указатели и масиви са сродни. Това произтича от факта, че името на всеки масив може да е различно като константа указател и от това, че използването на индекс операцията е твърде близко да използване на операцията ± . Структури и обединения struct[]{} struct union[]{} union Съкратения т.с. може да се запише само ако е в зоната на видимост на името на шаблона зададено при пълния спецификатор. Всички компонент на структурата едновременно присъстват в паметта т.е. те са едновременно активни. Всички компоненти на обединениетосподелят обща памет, чийто обем се изчислява от дължината на най-дългия вариант. Няма селектиране на активен вариант вэв всеки моминт може да се чете или записва от всеки вариант => всички варианти са едновременно активни, но споделят обща памет. Няма ограничение по отношение на данните, които могат да бъдат компонентите на структури и обединения. Структурата може да съдържа други структури и обединения , както и за вариантите важи същото. Компонентите на структурата може да бъде типово поле.Записва се така: [:],,,; Типовия спецификатор трябва да определя целочислен тип знаков или биззнаков. Константния израз дава дължината на битовото поле в битове. Ако броят на битовете, който е необходим да се резервират надхвърли дъжината на типовия спецификатор отпуска се автоматично нов компонент като преход между двата компонента не се реализира. Битови полета не могат да бъдат компоненти на обединенията, но могат да бъдат структури, които включват битови полета. При разполагане на компонентите на структури и обединения могат да се прескочат байтове с цел да се излезе на подходяща адресна граница. Не трябва да се разчита, че дължината на данната задължително ще съвпада с изчислената, получена чрез дължините на отделните компоненти. Желателно е компонентите да се подреждат по големина, от най-голяма към най-малка.. Достъпа до компонентите може да се изпълни по 2 начина, както за структурите, така и за обединенията: . изразът се изчислява до ст-ст с тип структура или обединение. -> израът се изчислява до ст-ст адрес, който е указател към структура или обединение. Ако компонентът е сложна данна той може да се уточнява по същия начин. Struct { int a,b; int c[20]; struct { char d[15]; float x;} y; int z;} q; *p; Всяка структура образува собствен клас. Доуточняват се структурите. q.a q.b q.c[5] q.y.d[2] p=&q; q.y.d[2] p -> y.d[2] Изрази Видове операнди: -константи: участват с ст-ст, която зависи от начина на записване.Конст. низове представяват адрес на 1-вия В от паметта където се съдържа низ -имена: имената на скал.данни в израза представят текущата ст-ст на данната; имената на струк. и обединенията представят самите тях; имената на ф-ции по същество са адрес на вх. точка на ф-цията; -обръщение към ф-ции: участват с върнатата от ф-ята ст-ст -междинни резултати: операнди, които се получават при изпълнение на операциите 1.Приоритетна таблица на операциите. Стрелката показва в какъв ред е приоритета. 1.( ) . -> [] ---> свръхприоритетни, те са операндно генериращи операции. 2.+ - ~ ! * & <--- Едноместни операции ++ -- size of преобразуване на тип 3.* / % ---> мултипликативни операциите 4. + - ---> адитивни 5. ---> изместване 6.= --->релации 7.== != ---> сравнение 8.& ---> побитово И 9.^ ---> сума по mod2 (побитово) 10. | ---> побитово ИЛИ 11.&& ---> логическо и 12.|| ---> логическо или 13. !: <--- условна операция 14.= *= /= %= += -= = &= |= ^= <--- Присвоявания 15. , ---> послед. изчисления 2.Обикновено аритметично преобразуване, при изпълнение на операндите се преобразуват до вид, при които операцията може да бъде изпълнена. Най-често преобразуването има за цел да се изравнят дължините или видът на вътрешното представяне. За числени данни се изпълняват еднакви преобразувания, известни под името обикновени аритметични преобразувания. То включва и правилата: - всеки Float се преобразува към double; - ако единия операнд е Double, другият задължително се преобразува към такъв; - всеки Char и Short се преобразува в Int, няма данни по-къси от Int; -беззнаковите Char и Short се преобразуват към безнаков Int; - Ако единия операнд е Long, другият също се преобразува към такъв; - Ако единия операнд е беззнаков Long, другият също се преобразува към такъв - Ако единия операнд е беззнаков Int, другият също се преобразува към такъв !!! Подредени правила, изброяват се точно в този ред. Това не е множество от правила. Тези правила се допълват от правилото за Min представимост. Трябва да се вземе минималния обем памет. 3.Преобразуване на указатели Възможен е преход от цели данни към указатели и обратно. Ако цяла данна трябва да се превърне в указател, най-напред се постига необходимата дължина, след което получената ст-ст се тълкува като беззнакова и после като указател. Прехода от указател към цяла ст-ст се извършва по обратния начин. Указателя се тълкува като беззнакова ст-ст, която се отсича на необходимата дължина. 4.Изпълнение на операциите а) едноместни операции -+ знаци за цели и плаващи данни; ОАП ~ - побитово НЕ. цели данни. ОАП ! - логическо НЕ. Анализира се разрядната решетка на операнда. Ако тя се състои само от нули, то стойността на операнда е лъжа. Ако ли не е истина. След което операнда се инвертира. * - косвено адресиране & - Получаване на адрес – операнда трябва да бъде с разпределена памет. Резултатът е адреса на операнда. ++ -- - Автоинкремента и автодекремента. цели, плаващи данни и указатели. ОАП. Могат да се запишат префиксно и суфиксно. При префиксно записване, се прочита операнда и неговата ст-ст се увеличава или намаля с 1. Паралелно с това се променя и паметта свързана с операнда. Операнда трябва да е локатор или L-value израз -> ако определя някаква памет. При суфиксно записване – прочита се операнда и това е резултата от операцията. Паралелно и независимо се променя и паметта свързана с него с 1. Int i, j,k ,m; i=10; j=5; k=++i; // k=11, i=11 m=j++; // m=5, j=6 size of () - Операндът може да е данна или типово име. Резултатът от операцията е брой байтове необхосими за съхраняване на данната или низа. Ако се използва име на масив, не се получава паметта на указателя, а се получава обема памет за самия масив. Int a[5] size of(a)->10 size of(int)->2 типово преобразуване () - Типът на операнда се преобразува насилствено към посоченото типово име. б) мултипликативни операции - * ,/ -За цели и плаващи данни, % само за целочислени данни.% - остатъкът от делението в) адитивни операции - +, - , цели и плаващи данни и указатели. Указател – указ. е реализуема операция, ако двата указателя са насочени към един и същ масив. Изваждат се двата указателя, резултата се дели на дължината на данните сочени от указателя и това е резултата от операцията. Дава разлика като брой елементи. г) изместване - Двата операнда трябва да са целочислени, измества се първия, а втория определя на колко разряда. При изместване на дясно, ако местения операнд е знаков, размножава се знака т.е. прави се аритметично изместване, а ако е беззнаков се прави логическо изместване на разрядната решетка и влизат нули. д) Релации – цели и плаващи данни и иказатели.ОАП. Указателите могат да се сравняват и за само ако са насочени към един и същи масив;сравняват се за == и != винаги, но не по адрес, а по разредност на решетката. Резултатът е 0, ако релацията не е изпълнена и 1, ако е изпълнена. А 11 дава 0 е)побитови операции- само за цели данни;ОАП; 0=False,1=True; сравняват се разредите ж) Логически операции &&, ||. Цели,плаващи данни и указатели. Оценяват се по своите разрядни решетки, ако е 0 – F, не нулева-T з)?: Условна операцията ? : - Изчислява се израз1 и ако той не е равен на 0, се преминава към оценяване на израз2, което е резултат от операнда. Ако резултата от израз1 е равен на 0 се оценява израз3 и това е резултатът от операцията. Почти винаги операцията ?: е скобирана. и) Присвояване – налице е множество присвоявания Присвояването е операция в С, а не оператор. При присвояване определящ е типа на получаващата данна. То се извършва по следните правила: -ако получаващата страна е цяла и по-дълга от присвояваната ст-ст най-напред се постига необходимата дължина като при беззнакови данни се извършва разширяване с водещи нули, а при знакови се размножава най-старшия бит; - ако получаващата страна е беззнакова най-напред се постига необходима дължина за присвояваната ст-ст по правило №1 и 3, след което получената ст-ст се разглежда като беззнакова и се извършва присвояване; - ако получаващата страна е цяла и по-къса, работи се с младшите разряди на присвояваната ст-ст, а старшите се губят; -Ако получаващата страна е плаваща трябва да се преобразува към цял тип: double-float-long-целиви тип;отсичат се дробните разреди -ако трябва да се премине от цял към плаващи: целочислен-long-float-double; =R // R – знак на операцията R= // (1) и (2) не са еквивалентни. Еквивалентни са само, ако (1) няма странични ефекти. й)последователно изчисление - , ,... , - разделител. Предизвиква последователно изчисление на изброените изрази. Резултатът от цялостния израз е стойността на последния израз (N-тия). I=0, j=5, k=0, l=3; Стойността на целия израз е 3. Среща се при оператор FOR. 5.Странични ефекти В класическото програмиране всяка функция представлява правило за изчисляване на някаква стойност. Ако освен тази задача, функцията върши и други действия се казва, че има странични ефекти. Всеки израз в езика С е също правило за изчисляване на стойност, но чрез включване на ++, -- и присвояване в списъка на операциите отпред, изразът може да върши и други дейности. Такъв израз има странични ефекти. Проблемите от такива изрази възникват в следствие на факта, че С регламентира приоритет на опертациите, но не и ред на подготовка на операндите, участващи в тях. !!! Ако данната се промени в израз, то тя е желателно да не участва повече като операнд. Така се намалява страничния ефект. Функции в С
1.Дефиниране на функции – поддържат се се две форми за дефиниране на функции (1) Класическа форма [][](,,,|void) [] {} (2) Прототипна форма [][](,,,|void) {} В (1) се изброяват параметри като имена или void, ако няма. Формалните параметри се декларират отделно под заглавието. Клас памет – най-често е празен, това се утъждествява с extern т.е. Функцията е с глобален обсег на действие. Може да се запише static. Статичните функции се защитават в текъщия файл и не могат да станат известни в другите файли чрез декларации. Типов спецификатор – Int по default. Определя типа на връщаната стойност или типа на указателя, ако функциията връща указател. Функциите могат да връщат всякакъв тип данни с изключение на функции и масиви, но могат да връщат указател към функции или масиви. Декларатор – Определя името на функцията. Може да се модифицира името със *. Върнатата стойност се променя като указател. Списък на формалните параметри – Могат да бъдат всякакви данни с изключение на функции. Ако формаления параметър трябва да бъде функция, той трябва да се декларира като указател към такава. При заместване на име на функция, формаления параметър указател автоматично ще се инициализира с входната точка на функцията. За С особеното е, че тази функция трябва да се вика чрез указател, а за С++ не е необходимо. При класическата форма, декларацията се прави вън от тялото. Всяка декларация не трябва да включва клас памет и инициализация. Класът памет е int по default. Тялото винаги се оформя като блок, дори да се състои от един единствен оператор. С допуска създаване на функции с променлив брой параметри.. При записване на заглавието след последния формален параметър трябва да се запише ' ,... '. Изброените формални параметри представляват задължителния брой параметри, но извикването може да се направи с по-голям брой аргументи – func(x,y,...). Даже е разрешено да се само '...' и това означава, че може да се извиква с нула и повече аргументи. 2.Активиране на функции ([],,,) Израз1 трябва да се изчислява до стойност с характер на входна стойност във функция и определя функцията как ще бъде извиквана за изпълнение (x>0:f1:f2)(...) // Частен случай: име Списъкът изрази в извикването представлява аргументите за текъщата активация. Изразите магат да се изчисляват за текущата активация. Изразите могат да се изчисляват за произволни данни с изключение на функции и масиви. Масив може да се използва, но той се тълкува като указател. Име на функция също може да се замести, но тя се тълкува като указател. Извикването предизвиква три проблема: - съответствието формален параметър – аргумент се извършва по позиция – То е позиционно! Самото заместване на данните е винаги по стойност! Няма заместване по указател! Ако искаме да предаваме по адрес – правим формален параметър, указатели, работим с указатели, а отвън подаваме адрес. За да е възможна работата с променлив брой аргументи, те се обработват от дясно на ляво и така се заместват в стек. По този начин задължително декларирания брой формални параметри винаги ще намери точно съответствие с някакви аргументи. Тази конвенция за заместване носи името С-конвенция.
|