ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 22.12.2021

Просмотров: 285

Скачиваний: 3

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

Привіт з Вінниці

Зверніть увагу на те, що при введенні рідка в функції gets на відмінність від функції scanf можна використовувати проміжки.

Цей приклад демонструє виведення значень покажчика або адреси:

#include stdio.h

main ()

{ int a, *b; /* обява цілого числа а і цілого числа, записаного за адресою */

b = &a; /* покажчик b отримує значення адреси змінної а */

a = 7; /* зміна а отримує значення 7 */

printf (” адреса змінної a = %p\n ”, &a);

printf (” значення змінної a = %d\n ”, a);

printf (” значення покажчика b = %p\n”, b );

printf (” значення змінної по адресі b = %d\n”, *b);

}

Результати її роботи:

адреса змінної а = FFE2

значення змінної а = 7

значення покажчика b = FFE2

значення змінної по адресі b = 7

Пояснимо, що таке FFE0. Це число, представлене в 16-річному коді:

FFE0 = F163 + F162 + F161 + F160 = 65 504, що відповідає двійковому числу 1111 1111 1110 0000, що означає адресу зміщення початку слова в сегменті оперативної пам’яті комп’ютера, де зберігається значення змінної а. Якщо сегмент пам’яті , на якій вирішувалась ця задача має об’єм 64 Кбайт (65 536), то двохбайтне значення змінної а знаходиться десь в його кінці.

Покажчики і операції з адесами

Раніше згадувалось про покажчики, які є змінними, що містять адреси інших змінних. Тому, що покажчик – це адреса деякого обєкту, то через нього можна звертатись до цього обєкту.

Унарна операція & дає адресу змінної, тому оператор y = &x; присвоює адресу х змінній у.


З

Y = & X

начення х



Операцію & можна використовувати тільки до змінних і елементів масиву; конструкції вигляду &(x = 7) або &28 недопустимі.

Унарна операція * сприймає свій операнд, як адресу деякого об’єкту і використовує цю адресу для вибірки вмісту, тому оператор Z = * Y; присвоює значення змінної, записаної по адресі Y.


Y


*Y

Z = * Y



Якщо y = & x; z = * y, то z = x, дивитись на рисунок:

Адреса Х




Значення х


Z = *Y






Значення Х






Про об’єкти, які складаються із знака * і адреси (наприклад, *а), необхідно повідомляти. Робиться це так:

int *a, *b, *c;

char * d;

Визначення виду char *d; говорить про те, що значення, записане за адресою d має тип char.

Покажчики можуть можуть зустрічатися і у виразах. Якщо у – покажчик на ціле значення , тобто мало місце визначення int *y, то *y може з’явитись там, де і будь-яка інша змінна, яка не є покажчиком. Таким чином допустимі такі вирази:

*у = 7;

*х* = 5;

(*z) ++;

Перше з них заносить число 7 в комірку за адресою у, друге збільшує значення за адресою х в 5 разів, третє – добавляє одиницю до вмісту комірки памяті з адресою z. В останньому випадку круглі дужки необхідні тому, що операції * та ++ з однаковим приоритетом виконуються справа наліво. В результаті, якщо, наприклад, *z = 5, то (*z)++ приведе до того, що *z = 6, a *z++ тільки змінить адресу z (операція ++ виконується над адресою z , а не над значенням *z по цій адресі).


Покажчики можна використовувати як операнди в арифметичних операціях. Якщо у – покажчик, то унарна операція у++ збільшує його значення ; тепер воно є адресою поточного елементу. Покажчики і цілі числа можна додавати. Конструкція у+n (у – покажчик, n – ціле число) задає адресу nго обєкту, на який вказує у. Це справедливо для будь-яких обєктів (int, char, float). Транслятор буде масштабувати приріст адреси у відповідності з типом, визначеним з відповідної обяви (int *y; char*y; float *y; і т.п.). Вираз у+=n означає виконання тих же дій, що і у = у + n;

Будь-яку адресу можливо перевірити на рівність (= =) або нерівність (!=)зі спеціальним значенням NULL, яке записується замість нуля. Слово NULL дозволяє визначити покажчик, який нічого не адресує.

Приклад програми, яка використовує покажчики:

#include stdio.h

main ()

{

unsigned char *a,*b;

const char S[ ] = ” ВНТУ ”;

printf (” адрес S[ ]:% p \n ”, S); /* на екран дисплея виведеться адреса першого елемента в рядку S */;

puts (”введіть через кому значення покажчика і символ ”);

/* показано, як переносити текст в функції виведення, якщо він дуже довгий для одного рядка */

scanf (”% р, % с”, &d, &b); /*введення значень покажчика і символа */

*a = b;

printf (”значення b дорівнює: % c \n ”, b);

printf (” значення b записаного по адресі: % p \n ”, &b);

printf (” За адресою а записане число: % d \n ”, *a);

printf (” значення покажчика а дорівнює: % p \n ”, a);

printf (” % s \n ” , s);

printf (” *++a = %d; *( a + 2 ) = % d; ++*a = % d; *a + 2 = % d ”, *++a, *(a + 2 ), ++*a, *a + 2);

}

Результати виконання можна представити приблизно так:

Адреса S[ ] : FFDC

Введіть через кому значення покажчика і символ f f e 3 , 2

Значення b дорівнює : 2

Значення b записане по адресі : FFDB

За адресою а записане число : 50

Значення покажчика а дорівнює : FFE3

ВДТУ

*++a = 17; *(a + 2) = 1; ++*a = 51; *a + 2 = 52;

Введене значення покажчика d f f e 3 в 16-му коді і значення “2” символа b. Номер символа “2” в код. Таблиці дорівнює 50. Прокоментуємо останній рядок:

*++a – це значення типу unsigned char, записане по адресі ffe4;

*(a + 2) – це значення по адресі, збільшеній відносно а на дві масштабні одиниці ( в прикладі ffe5);

++*a – це значення по адресі а , збільшене на 1 ( в прикладі номер символа “2” плюс 1 , тобто 50 + 1 = 51);

*a + 2 – це значення по адресі а, збільшене на 2 ( в прикладі

50 + 2 = 52);

Зверніть увагу, що унарна операція * має більш високий пріоритет, ніж бінарна операція + .

Домашнє завдання: ввести замість адреси ffe3 ffdc + 1 = ffdd, а замість “2” знак “!”. Що буде?

Перетворення типів

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

Основні правила перетворення типів:

  1. Якщо виконується операція над змінними двох різних типів, обидві величини приводяться до “вищого” з двох типів. Цей процес називається “підвищенням” типу;

  2. Послідовність назв типів, впорядкованих від ”вищого” до “нижчого” виглядає наступним чином:


Double, float, long, int, short, char,

Застосування ключового слова unsigned підвищує ранг відповідного типу данних зі знаком.

  1. В операторі присвоєння кінцевий результат обчислення виразу в правій частині приводиться до типу змінної, котрій було присвоєне це значення. Даний процес може призвести до “підвищення ” типу або до “пониження”, при якому величини приводяться до типу даних, що має більш низький пріоритет.

“Підвищення ” типу проходить гладко, а “пониження ” може призвести до ускладнень.

m ice = 1.6 + 1.7 3.3 = 3

mice = ((int)1.6 + (int)1.7 ); 1 + 1 = 2


Питання для самоконтроля

  1. Чому мова Сі отримала таке поширене використання при програмуванні?

  2. Перелічіть етапи створення програми на мові Сі.

  3. Що таке препроцесор? Для чого він використовується?

  4. Які команди препроцесора ви знаєте?

  5. З чого складається будь-яка програма на мові Сі?

  6. З якої функції починається програма на мові Сі?

  7. Що входить до алфавіту мови Сі?

  8. Яка відмінність оператора присвоєння від арифметичних операцій Паскаля?

  9. Поясніть дію операцій інкремента і декремента.

  10. Правила використання коментарів в мові Сі.

  11. Які знаки логічних і порозрядних операцій в мові Сі ви знаєте?

  12. Які типи даних оголошують змінні цілого типу? Приклади.

  13. Які типи даних оголошують змінні дійсного типу? Приклади.

  14. Як збільшити діапазон значень для цілого і дійсного типів?

  15. Для чого призначений переліковий тип enum ?

  16. Які ви знаєте символи перетворення в функції виведення printf?

  17. Які ви знаєте керуючі символьні константи ?

  18. Пояснити, як працює функція форматного введення.

  19. Які символи перетворення функції printf допускаються в функції scanf?

  20. Чому при форматному введенні масиву в функції scanf не використовується знак &?

  21. Яка функція дозволяє ввести тільки один символ?

  22. Що таке покажчик? Приклади використання.

  23. Як працює тернарна операція в мові Сі?

  24. Запишіть вираз мовою Сі: “Збільшити на одиницю вміст комірки памяті з адресою Z ”.

  25. Запишіть вираз мовою Сі: “Збільшити значення по адресі х в 5 разів”

  26. Які ви знаєте правила перетворення типів?

  27. Поясніть приоритет виконання операцій мовою Сі.


ЛІТЕРАТУРА

  1. Л.М.Kлимова С++ Практическое программирование

Учебное пособие каф. ПМ МГТУ Москва 2001г.

  1. Г.А.Павловская , Ю.А.Щупак С/С++ Структурное программирование

Практикум. Учебник “Питер ” М – С-Пет. 2002г.

3. Уэйт М. Язык Си Из –во “ Мир” 1988г.

  1. П.Киммел Borland C++5 BHV – Санкт – Петербург 2001г.

  2. Т.А. Павловская С/С++ Программирование на языке высокого уровня

Учебник для студентов Питер – 2001г.

  1. Страуструп Б. Программирование на С++

  2. Шилдт Г. Программирование на С++

  3. В.А.Юлин, И.Р.Булатова Приглашение к СИ

Минск “Высшая школа 1990г.

  1. Подбельский В.В. Программирование на языке Си, М: Финансы і статистика, 2002 год.

  2. Герберт Шилдт, Полный справочник по Си, Из.дом «Вильямс» М,2002

12