Студопедия.Орг Главная | Случайная страница | Контакты | Мы поможем в написании вашей работы!  
 

Static (статична)



Щоб обмежити доступ до змінних, дозволяючи зберегти їх значення між викриками функцій, слід оголошувати їх статичними. Статична змінна може бути внутрішньою або зовнішньою. Внутрішні статичні змінні локальні по відношенню до окремої функції, подібно автоматичним, проте на відміну від останніх продовжують існувати, а не виникають та знищуються при кожній активації функції. Це означає, що внутрішні статичні змінні є власною, постійною пам'яттю для функції:

int funct(void)

{

static int value=20;

...

}

Компілятор відведе постійну область пам'яті для змінної value та проініціалізує її значення. Ця ініціалізація не повторюватиметься щоразу при активації функції. В подальшому змінна матиме те значення, яке вона отримала по завершенні її останньої роботи. Слід відзначити, що така змінна буде назавжди прихованою для завантажувача даної програми. Тому область дії статичних змінних обмежена функцією, в якій вона була оголошена, а функції не мають доступу до статичних змінних, оголошених в інших функціях.

Зовнішні статичні об'єкти відомі в тому файлі, в якому описані, проте в інших файлах вони невідомі. Таким чином, забезпечується спосіб об'єднання даних та маніпулюючи ними підпрограм таким чином, що інші підпрограми та дані у будь-якому випадку не зможуть конфліктувати з ними.

1.16.8 Додаткові можливості функції main()

Потрібно зауважити, що функція main() може як повертати деяке значення в операційну систему, так і приймати параметри.

тип main(int argc, char* argv[], char *env[]) { /* … */ }

Імена параметрів можуть мати будь-які назви, але прийнято використовувати argc, argv та env. Перший параметр argc містить ціле число аргументів командного рядка, що посилається функції main(); argv - це масив покажчиків на рядки. Для версії ДОС argv[0] містить повний шлях програми, що в даний момент виконується, argv[1] та argv[2] відповідно вказує на перший та другий після імені програми параметри командного рядка, argv[argc-1] вказує на останній аргумент, argv[argc] містить NULL.

env - це масив покажчиків на рядки, причому кожний елемент env[] містить рядок типу ENVVAR=значення. ENVVAR - це ім'я змінної середовища.

Можливо для першого ознайомлення з Сi ця інформація не є обов'язковою, проте не може не зацікавити приклад програми, що демонструє найпростіший шлях використання аргументів, що передаються функції main():

/* Використання аргументів функції main() */

#include <stdio.h>

#include <stdlib.h>

void main(int argc, char *argv[], char *env[])

{

int i;

printf("Значення argc = %d \n\n",argc);

printf("В командному рядку міститься %d параметрів \n",argc);

for (i=0; i<argc; i++)

printf(" argv[%d]: %s\n", i, argv[i]);

printf("Середовище містить наступні рядки:\n");

for (i=0; env[i]!= NULL; i++)

printf(" env[%d]: %s\n", i, env[i]);

}

Організуємо виконання програми з командним рядком таким чином:

C:> c:\tc\testargs.exe 1_st_arg "2_arg " 3 4 "dummy" stop!

В результаті роботи програми ви отримаєте приблизно наступне:

Значення argc = 7

В командному рядку міститься 7 параметрів

argv[0]: c:\tc\testargs.exe

argv[1]: 1_st_arg

argv[2]: 2_arg

argv[3]: 3

argv[4]: 4

argv[5]: dummy

argv[6]: stop!

Середовище містить наступні рядки:

env[0]: COMSPEC=C:\COMMAND.COM

env[1]: PROMPT=$p $g

env[2]: PATH=C:\SPRINT;C:\DOS;C:\TC

Максимальна загальна довжина командного рядка, включаючи пробіли та ім'я самої програми, не може перевищувати 128 символів, що є DOS-обмеженням.

1.17 Складені оголошення

Прості оголошення в мові Сі дозволяють визначати прості змінні, масиви, покажчики, функції, структури та об'єднання.

В найпростішому випадку, якщо оголошується проста змінна базового типу, типу структури або об'єднання, ідентифікатор описується типу, що заданий специфікацією типу.

Для оголошення масиву значень деякого типу, функції, що повертає значення деякого типу, або покажчика на значення деякого типу, ідентифікатор доповнюється відповідно квадратними дужками […] справа, круглими дужками (…) справа або ознакою покажчика - зірочкою (*) зліва.

Наступні приклади ілюструють найпростіші форми оголошень:

int list[20]; /* масив list із 20 цілих значень */

char *cp; /* покажчик cp на значення типу char */

double func(); /* функція func(), що повертає значення типу double*/

Синтаксис оголошення:

[ клас_пам'яті ] тип ідентифікатор [ = ініціалізатор ];

Оголошення складаються з чотирьох частин:

1. необов'язкового специфікатора класу пам'яті (auto, register, static, extern);

2. базового типу або типу користувача;

3. оголошуючої частини;

4. необов'язкового ініціалізатора.

Оголошуюча частина в свою чергу складається з ідентифікатора і, можливо, операторів оголошення. Найчастіше використовуються наступні оператори оголошення (таблиця 1.18).

Таблиця 1.18. "Оператори оголошення"

* покажчик префікс
*const константний покажчик префікс
& посилання (адреса) префікс
[ ] масив суфікс
() функція суфікс

Суфіксні оператори оголошення "міцніше зв'язані" з ім'ям, ніж префіксні. Тому typename *str[]; означає масив покажчиків на деякі об'єкти, а для визначення типів таких як "покажчик на функцію" необхідно використовувати дужки.

Складене оголошення - це ідентифікатор, що доповнений більше ніж однією ознакою масиву, покажчика, або функції.

З одним ідентифікатором можна створити множину різних комбінацій ознак типу масив, покажчик або функція. Причому, деякі комбінації неприпустимі. Наприклад, масив не може містити в якості елементів функцію, а функція не може повертати масив або функцію.

При інтерпретації складених оголошень спочатку розглядають квадратні і круглі дужки, що розташовані справа від ідентифікатора. Квадратні і круглі дужки мають однаковий пріоритет. Вони інтерпретуються зліва направо. Після них розглядаються зірочки, що розташовані зліва від ідентифікатора. Специфікація типу розглядається на останньому етапі, після того, як все складене оголошення проінтерпретоване.

Круглі дужки можуть також використовуватися для зміни існуючого по замовчуванню порядку інтерпретації оголошення. Наприклад:

int *func(); /*функція, що повертає покажчик на int */

int (*func)();/*покажчик на функцію, що повертає int */

Алгоритм інтерпретації складених оголошень:

1. Знайти ідентифікатор (якщо їх декілька, то необхідно почати з того, який знаходить ближче до "середини" складеного оголошення).

2. Подивитися вправо:

• Якщо справа розташована відкриваюча кругла дужка - тоді це функція, а вираз, що розташований між цією відкриваючою дужкою '(' і відповідною їй закриваючою дужкою ')' необхідно інтерпретувати як параметри функції.

• Якщо справа стоїть відкриваюча квадратна дужка '[' - тоді це масив і вираз між відповідними квадратними дужками […] необхідно інтерпретувати як розмір масиву. Примітка: якщо масив багатовимірний, то за дужками […] розташовується ще одна або декілька серій квадратних дужок […].

• Якщо на будь-якому етапі інтерпретації справа зустрічається закриваюча кругла дужка ')', то необхідно спочатку повністю провести інтерпретацію всередині даної пари круглих дужок, а потім подовжити інтерпретацію справа від закриваючої круглої дужки ')'.

3. Якщо зліва від проінтерпретованого виразу розташована зірочка і:

• проінтерпретований вираз є функцією, то вона повертає покажчик;

• проінтерпретований вираз є масивом, то кожний елемент цього масиву є покажчиком;

• проінтерпретований вираз не є ні функцію, ні масивом, то вираз є покажчиком.

4. Застосувати описані вище правила (2-3 пункт алгоритму) ще раз.

5. Проінтерпретувати специфікацію типу даних.

Приклад інтерпретації складених оголошень:

1. Ідентифікатор var оголошений як

2. покажчик на

3. функцію, що приймає в якості аргументу масив із ста значень типу char і повертає

4. покажчик на

5. масив із ста елементів, кожний з яких є

6. покажчиком на

7. значення типу char.

1.17.1 Описи з модифікаторами

Використання в оголошеннях спеціальних ключових слів (модифікаторів) дозволяють надавати оголошенням спеціального змісту. Інформація, яку несуть в собі модифікатори, використовуються компілятором мови Сі в процесі генерування коду.

Розглянемо правила інтерпретації оголошень, що містять модифікатори const, volatile, cdecl, pascal, near, far, huge, interrupt.

Модифікатори cdecl, pascal, interrupt повинні розташовуватися безпосередньо перед ідентифікатором.

Модифікатори const, volatile, near, far, huge впливають або на ідентифікатор, або на ознаку покажчика (зірочку), що розташована безпосередньо справа від модифікатора. Якщо справа розташований ідентифікатор, то модифікується тип об'єкта, що іменується даним ідентифікатором. Якщо ж справа розташована зірочка, то ця зірочка представляє собою покажчик на модифікований тип. Таким чином, конструкція

модифікатор *

читається як "покажчик на модифікований тип".

Наприклад,

int const *p; /* покажчик на цілу константу */

int *const p; /* константний покажчик на величину типу int */

Модифікатори типу const і volatile можуть також розташовуватися і перед специфікацією типу.

В ТС використання модифікаторів near, far, huge обмежене: вони можуть бути записані тільки перед ідентифікатором функції або перед ознакою покажчика (зірочкою).

Допускається більше одного модифікатора для одного об'єкта (або елемента оголошення). В наступному прикладі тип функції func модифікується одночасно спеціальними ключовими словами far і pascal. Порядок ключових слів неважливий, тобто комбінації far pascal і pascal far мають однаковий зміст.

int far * pascal far func();

Тип значення, що повертається функцією func, представляє собою покажчик на значення типу int. Тип цих значень модифікований спеціальним ключовим словом far.

Як і звичайно, в оголошенні можуть бути використані круглі дужки для зміни порядку його інтерпретації.

В даному прикладі наведене оголошення з різними варіантами розташування модифікатора far. Враховуючи правило, відповідно до якого модифікатор впливає на елемент оголошення, розташований справа від нього, можна інтерпретувати це оголошення наступним чином.

1. Ідентифікатор getint оголошений як

2. покажчик на far

3. функцію, що приймає

4. один аргумент, який є покажчиком на far

5. значення типу int

6. і повертає покажчик на far

7. значення типу char

1.17.2 Модифікатори const і volatile

Про модифікатор const йшла мова в розділі 1.2.3."Константи". Модифікатор const не допускає явного присвоювання змінній або інших дій, що можуть вплинути на зміну її значення, таких як виконання операції інкременту і декременту. Значення покажчика, що оголошений з модифікатором const, не може бути зміненим, на відміну від значення об'єкта, на який він вказує.

Модифікатори volatile і const протилежні за змістом.

Модифікатор volatile вказує на те, що значення змінної може бути зміненим; але не тільки безпосередньо програмою, а також і зовнішнім впливом (наприклад, програмою обробки переривань, або, якщо змінна відповідає порту введення/виведення, обміном із зовнішнім пристроєм). Оголошення об'єкта з модифікатором volatile попереджує компілятор мови Сі, чого не слід робити

Можливим також є одночасне використання в оголошенні модифікаторів const і volatile. Це означає, що значення змінної не може модифікуватися програмою, але піддається зовнішньому впливу.

Якщо з модифікатором const або volatile оголошується змінна складеного типу, то дія модифікатора розповсюджується на всі його складові елементи.

Примітка. При відсутності в оголошенні специфікації типу і присутності модифікатора const або volatile мається на увазі тип int.

Приклади:

float const pi=3.14159265;

const maxint=32767;

char *const str= "Деякий рядок."; /* покажчик-константа */

char const *str2= "Рядок";/* покажчик на константний рядок */

Із врахуванням наведених вище оголошень наступні оператори неприпустимими.

pi=3.0; /* присвоювання значення константі */

i=maxint--; /* зменшення константи */

str="Other string"; /* присвоювання значення константі-покажчику */

Однак виклик функції strcpy(str,"String"); припустимий, так як в даному випадку здійснюється посимвольне копіювання рядка в область пам'яті, на яку вказує покажчик.

Аналогічно, якщо покажчик на тип const присвоїти покажчику на тип, відмінний від const, то через отриманий покажчик можна здійснювати присвоювання.

1.17.3 Модифікатори cdecl і pascal

Результатом роботи компілятора мови Сі є файл, що містить об'єктний код програми. Файли з об'єктним кодом, що отримуються в результаті компіляції всіх файлів програми, компоновщик об'єднує в один файл виконання.

При компіляції всі глобальні ідентифікатори програми, тобто імена функцій і глобальних змінних, зберігаються в об'єктному коді і використовуються компоновщиком в процесі роботи. По замовчуванню ці ідентифікатори зберігаються в своєму початковому вигляді. Крім того, в якості першого символу кожного ідентифікатора компілятор мови Сі додає символ підкреслення.

Компоновщик по замовчуванню розрізняє великі та малі літери, тому ідентифікатори, що використовуються в різних файлах програми для іменування одного і того самого об'єкта, повинні повністю співпадати з точки зору як орфографії, так і регістрів літер. Для здійснення співпадіння ідентифікаторів, що використовуються в різномовних файлах, використовуються модифікатори pascal і cdecl.

Використання модифікатора pascal до ідентифікатора призводить до того, що ідентифікатор перетворюється до верхнього регістру і до нього не додається символ підкреслення. Цей ідентифікатор не може використовуватися для іменування в програмі на мові Сі глобального об'єкта, який використовується також в програмі на мові Паскаль. В об'єктному коді, що згенерований компілятором мови Сі, і в об'єктному коді, що згенерований компілятором мови Паскаль, ідентифікатор буде представлений ідентично.

Якщо модифікатор pascal застосовується до ідентифікатора функції, то він здійснює вплив також і на передачу аргументів функції. Засилання аргументів у стек здійснюється в цьому випадку не в оберненому порядку, як прийнято в компіляторах мови Сі, а в прямому - першим засилається в стек перший аргумент.

Функція типу pascal не може мати змінне число параметрів, як, наприклад, функція printf ().

Існує ще один модифікатор, яка присвоює всім функціям і покажчикам на функції тип pascal. Це означає, що вони будуть використовувати послідовність виклику, що прийнята в мові Паскаль, а їх ідентифікатори будуть можливими для виклику з програми на Паскалі. При цьому можна сказати, що деякі функції і покажчики на функції використовують викликаючу послідовність, прийняту в мові Сі, а їх ідентифікатори мають традиційний вигляд для ідентифікаторів мови Сі. Для цього їх оголошення повинні містити модифікатор cdecl.

1.17.4 Модифікатори near, far, huge

Ці модифікатори здійснюють вплив на роботу з адресами об'єктів.

Компілятор мови Сі дозволяє використовувати при компіляції одну з декількох моделей пам'яті.

Використання моделі пам'яті визначає розміщення програми і даних в ОП, а також внутрішній формат покажчиків. Однак при використанні будь-якої моделі пам'яті можна оголосити покажчик з форматом, що відрізняється від прийнятого по замовчуванню. Це здійснюється за допомогою модифікаторів near, far і huge.

Покажчик типу near - 16-бітовий; для визначення адреси об'єкта він використовує зсув відносно поточного вмісту сегментного регістру. Для покажчика типу near доступна пам'ять обмежена розміром поточного 64-кілобайтного сегмента даних.

Покажчик типу far - 32-бітовий; він містить як адресу сегменту, так і зсув. При використанні покажчиків типу far припустимі звернення до пам'яті в межах 1-мегабайтного адресного простору, однак значення покажчика типу far циклічно змінюється в межах 64-кілобайтного сегменту.

Покажчик типу huge - 32-бітовий; він також містить адресу сегменту і зсув. Значення покажчика типу huge може бути змінене в межах 1-мегабайтного адресного простору. В ТС покажчик huge завжди зберігається в нормалізованому форматі.

1.17.5 Модифікатор interrupt

Модифікатор interrupt призначений для оголошення функцій, що працюють з векторами переривань процесору. Для функції типу interrupt при компіляції генерується додатковий код в точці входу і виходу з функції, для збереження і відновлення значень регістрів процесора.

Функції переривань слід оголошувати з типом повернення void. Модифікатор interrupt не може використовуватися спільно з модифікаторами near, far та huge.





Дата публикования: 2015-01-23; Прочитано: 482 | Нарушение авторского права страницы | Мы поможем в написании вашей работы!



studopedia.org - Студопедия.Орг - 2014-2024 год. Студопедия не является автором материалов, которые размещены. Но предоставляет возможность бесплатного использования (0.015 с)...