ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 22.12.2021
Просмотров: 283
Скачиваний: 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” знак “!”. Що буде?
Перетворення типів
Повинні використовуватись змінні і константи одного типу. При змішуванні компілятор Сі не вважає програму правильною, як це було на Паскалі. Замість цього компілятор використовує набір правил для перетворення типів.
Основні правила перетворення типів:
-
Якщо виконується операція над змінними двох різних типів, обидві величини приводяться до “вищого” з двох типів. Цей процес називається “підвищенням” типу;
-
Послідовність назв типів, впорядкованих від ”вищого” до “нижчого” виглядає наступним чином:
Double, float, long, int, short, char,
Застосування ключового слова unsigned підвищує ранг відповідного типу данних зі знаком.
-
В операторі присвоєння кінцевий результат обчислення виразу в правій частині приводиться до типу змінної, котрій було присвоєне це значення. Даний процес може призвести до “підвищення ” типу або до “пониження”, при якому величини приводяться до типу даних, що має більш низький пріоритет.
“Підвищення ” типу проходить гладко, а “пониження ” може призвести до ускладнень.
m ice = 1.6 + 1.7 3.3 = 3
mice = ((int)1.6 + (int)1.7 ); 1 + 1 = 2
Питання для самоконтроля
-
Чому мова Сі отримала таке поширене використання при програмуванні?
-
Перелічіть етапи створення програми на мові Сі.
-
Що таке препроцесор? Для чого він використовується?
-
Які команди препроцесора ви знаєте?
-
З чого складається будь-яка програма на мові Сі?
-
З якої функції починається програма на мові Сі?
-
Що входить до алфавіту мови Сі?
-
Яка відмінність оператора присвоєння від арифметичних операцій Паскаля?
-
Поясніть дію операцій інкремента і декремента.
-
Правила використання коментарів в мові Сі.
-
Які знаки логічних і порозрядних операцій в мові Сі ви знаєте?
-
Які типи даних оголошують змінні цілого типу? Приклади.
-
Які типи даних оголошують змінні дійсного типу? Приклади.
-
Як збільшити діапазон значень для цілого і дійсного типів?
-
Для чого призначений переліковий тип enum ?
-
Які ви знаєте символи перетворення в функції виведення printf?
-
Які ви знаєте керуючі символьні константи ?
-
Пояснити, як працює функція форматного введення.
-
Які символи перетворення функції printf допускаються в функції scanf?
-
Чому при форматному введенні масиву в функції scanf не використовується знак &?
-
Яка функція дозволяє ввести тільки один символ?
-
Що таке покажчик? Приклади використання.
-
Як працює тернарна операція в мові Сі?
-
Запишіть вираз мовою Сі: “Збільшити на одиницю вміст комірки пам’яті з адресою Z ”.
-
Запишіть вираз мовою Сі: “Збільшити значення по адресі х в 5 разів”
-
Які ви знаєте правила перетворення типів?
-
Поясніть приоритет виконання операцій мовою Сі.
ЛІТЕРАТУРА
-
Л.М.Kлимова С++ Практическое программирование
Учебное пособие каф. ПМ МГТУ Москва 2001г.
-
Г.А.Павловская , Ю.А.Щупак С/С++ Структурное программирование
Практикум. Учебник “Питер ” М – С-Пет. 2002г.
3. Уэйт М. Язык Си Из –во “ Мир” 1988г.
-
П.Киммел Borland C++5 BHV – Санкт – Петербург 2001г.
-
Т.А. Павловская С/С++ Программирование на языке высокого уровня
Учебник для студентов Питер – 2001г.
-
Страуструп Б. Программирование на С++
-
Шилдт Г. Программирование на С++
-
В.А.Юлин, И.Р.Булатова Приглашение к СИ
Минск “Высшая школа” 1990г.
-
Подбельский В.В. Программирование на языке Си, М: Финансы і статистика, 2002 год.
-
Герберт Шилдт, Полный справочник по Си, Из.дом «Вильямс» М,2002