Бублик Володимир Васильович Програмування - 2 Лекція 3. Базові поняття програмування. Сталі та змінні    Лекції для студентів 2 курсу
Літерали   Літерал (з латинського  literal  — буквальний) — це найпростіший об’єкт, що позначає сам себе. Цілі літерали 100 //десятковий запис 0144 //вісімковий ( o ctal ) 0х64 //шістнадцятковий ( hexadecimal ,  he x ) Вісімковими і шістнадцятковими константами варто користуватися лише для типів без знаку, інакше на комп’ютерах з доповняльним кодом можна зіткнутися із несподіванками типу значення  –1  для константи  0xffffffff
Літерали   Уточнення типу числового літералу U,  L  або  UL 2147483648U 2147483648L   2147483648UL F  або  L 1.0F 3.1415926535897932 L
Літерали   Символьні літерали // звичайні символи ’ ?’, ’f’, ’ї’
Літерали   Символьні літерали // вісімкові коди  ’ \77’ // символ ’?’ ’ \144’ // символ ’f’ ’ \365’ // символ ’ї’ ( з точністю до кодової таблиці ) ’ \11’ // символ табуляції ’ \12’ // символ нового рядка ’ \14’ // символ нової сторінки
Літерали   Символьні літерали // шістнадцяткові коди  ’ \x3f’ // символ ’?’ ’ \x66’ // символ ’f’ ’ \x10’ // символ нового рядка
Літерали   Символьні літерали // службові символи ’ \t’ // символ табуляції ’ \n’ // символ нового рядка ’ \f’ // символ нової сторінки Як бачимо, деякі з символів можна записати різними рівносильними способами: ’ \x10’, ’\12’ і ’\n’  ’ f’, ’\144’ і ’\x66’
Літерали   Багатосимвольні літерали (рядки) ” A” // послідовність, складена з ’A’ і ’\0’ ″ Це константа, складена із символів″ ” This is another string” ” Наступний рядок містить службові символи” ” \n№п/п\tНазва\tКількість\n” Виведеться як № п/п Назва Кількість
Літерали  vs.  Іменовані об'єкти   Літерали не потребують визначення, бо позначають самі себе, а запис літералу однозначно визначає його тип. Іменовані об'єкти  вимагають попереднього визначення (створення)   або  оголошення . Визначення і оголошення визначають ім'я і тип об'єкту. Визначення приводить до  створення об'єкту в пам'яті , тоді як оголошення посилається на об'єкт, створений в іншому місці. Визначення звичайно суміщують з ініціалізацією.
Визначення сталих const  float pi = 3.14159; const  float Avogadro =6.02252e23; const  double dpi = 3.141592653589793; const  char tab = ‘\t’; const  char title[] = ”C++ Programming Language”; const int sample; // сталу необхідно визначити! const int sample = 1756; sample = 456; // значення сталої не можна змінити!
Визначення змінних int i= 1 , j= 1 , k= 1 ; // добре unsinged long counter= 0 ;  // змінні корисно ініціювати double a = 0.0 , b= 1.0 ; double eps =  0.000001 ; double x; //визначення з наступним присвоєнням x = 0;  //чому не ініціалізація  double x  = 0;  ? double x; //не годиться! Перше присвоєння надто  ………… .. x = 0; // далеко  від визначення
Розміщення в пам'яті
Арифметичне присвоєння x = e; де  x  – іменуючий вираз,  e  – арифметичний вираз Обчислити  lvalue (x) Обчислити  rvalue (e) Переслати  rvalue (e)  до  lvalue (x) Значенням виразу  x = e  вважати нове значення value (x) Яке з них  lvalue  чи  rvalue ?  ― Залежно від контексту
Приклад арифметичного присвоєння x = y; lvalue (x)
Приклад арифметичного присвоєння x = y; rvalue (y)
Приклад арифметичного присвоєння x = y; Переслати
Приклади присвоєнь s = pi * r * r; i = j+k; Суміщене присвоєння i += k; // i = i+k i >>= k; // i = i>>k Інкремент (декремент)  постфіксний // нехай k==1 j=k++ //j=k; k=k+1; // j==1; k==2 (i=++(j=++k))++  ; ??? префіксний // нехай k==1 j=++k  //k=k+1; j=k; // j==2; k==2
Композиція присвоєнь u = v = w;  читається як  u =  ( v = w ) ; rvalue (w)  ―›  lvalue (v) rvalue (v)  ―›  lvalue (u) (u = v) = w; rvalue (v)  ―›  lvalue (u) rvalue (w)  ―›  lvalue (u) // що б це значило?
Зведення типів 1. С (старомодне) week  ―›   int int (monday)  або  (int) Monday int  ―›  week (week) i   2. С++ (новітнє) const_cast, dynamic_cast, static_cast   y = static_cast<double>( x );  Дуже обережно! Може з'явитися багато проблем
Указник ( pointer) int  * ptrI; float *px, y, z; float *px, *py, *pz; Визначення без ініціалізації приводять до заповнення пам'яті сміттям. Засмічені указники ( dangling pointer)  небезпечні ! float x, *px; сміття сміття некоректні дані некоректна адреса
Pointer vs. goto Указники приводять до тих же проблем в структурах даних, до яких приводять оператори переходу в структурах керування. Скрізь, де можна, уникаємо указників. Якщо вживаємо, то дотримуємось  суворої  дисципліни! Якщо значення указника невідоме, ініціалізуємо його  нулем float *px = 0; Якщо значення указника не нуль, то з ним зв'язані  два  елементи пам'яті!
Адресування і розіменування x=0.25; px =  & x; & одномісна операція адресування lvalue(px) rvalue(px) == lvalue (x) == rvalue(&x)
Адресування і розіменування Взаємна оберненість операцій над пам'яттю &(*px) == px px == *(&px)
Адресування і розіменування cout<<   * px; *  одномісна операція розіменування rvalue(px) == lvalue(x) rvalue(*px) == rvalue(x)
Динамічне виділення пам'яті float *p =  new  float; new  операція виділення нового елемента пам'яті, його адреса зберігається в p, значення *p заповнено сміттям px = new float; if (px == 0) // вільної пам’яті немає сміття
Динамічне виділення і ініціалізація пам'яті float *p =  new  float(0.333333); Тепер значення *p коректне
Правило гарного тону Якщо ви виділили динамічну пам’ять за допомогою команди  new  не забудьте своєчасно звільнити її командою  delete  та обнулити указник float *p =  new  float(0.333333); // робіть все, що вам потрібно delete  p; p = 0 ;
Звільнення памяті double *pd = new double(5.2); cout<<pd<<endl; //  0 x00 4419 B0  cout<<*pd<<endl; //5.2 delete  pd; cout<<pd<<endl; //  0 x00 4419 B0 cout<<*pd<<endl; //-1.45682e+144 double *n ew_ pd = new double; cout<<n ew_ pd<<endl; //  0 x00 4419 B0 cout<<*pd<<endl; //-6.27744t+066 cout<<*n ew_ pd<<endl;
Звільнення памяті double *pd = new double(5.2); cout<<pd<<endl; //  0 x00 4419 B0  cout<<*pd<<endl; //5.2 delete  pd; // Правило гарного тону pd = 0;
Сталі величини і указники Указник  сталої   const float pi = 3.14159; const float  *piPtr = &pi  ; //*piPtr  = 4; ERROR!
Сталі величини і указники float x = 1; const  float* px = &x; x =3; cout<<*px<<endl; //*px  = 4;  як і раніше  ERROR! Указник сталої не має права змінити об'єкт, але безпосередня зміна об'єкту, якщо він не сталий можлива
Сталі величини і указники Сталий  указник float  x  = 0.25; float  *const  px = &x ; //px =  &y;  ERROR!
Сталі величини і указники Сталий  указник  сталої   const float pi = 3.14159; const float   *const  piPtr = &pi ; //*piPtr  = 4; ERROR! //piPtr = &nAvogadro; ERROR!
Безтипові указники void *voidPtr; //Що б це значило? voidPtr char * str “ \nabcdefghij” 00 A0 69 68 67 66 65 64 63 62 61 0 A
Безтипові указники void *voidPtr; //Що б це значило? voidPtr Якби це був Бейсик “ abcdefghij” 00 A0 69 68 67 66 65 64 63 62 61 0 A
Безтипові указники void *voidPtr; //Що б це значило? voidPtr short int * i 24842 A0 00 69 68 67 66 65 64 63 62 61 0 A
Безтипові указники void *voidPtr; //Що б це значило? voidPtr float * x 4.17596e+021 A0 00 69 68 67 66 65 64 63 62 61 0 A
Безтипові указники void *voidPtr; //Що б це значило? voidPtr int * k 1667391754 A0 00 69 68 67 66 65 64 63 62 61 0 A
Безтипові указники void *voidPtr; //Що б це значило? float *pf = new float(3.1); double *pd = new double(5.2); voidPtr = pf; cout<<voidPtr<<endl; // 0 x00 4419 F0 // cout<<*voidPtr<<endl; розіменування неможливе voidPtr = pd; cout<<voidPtr<<endl; // 0 x00 4419 B0
Символьний указник char *c = new char; cout<<*c<<endl; char *cc = new char('a'); cout<<*cc<<endl; // char *str = new char(“String?“); char *str = &quot;Operation New is not needed&quot;; cout<<str<<endl;
Операцій над указниками float *p1=new float(1), *p2=new float(2); cout<<p2; //0x004418F0 Порівняння на рівність або нерівність p1 == p2; p1 > p2;… if(p2>p1) cout<<&quot;p2>p1&quot;<<endl; else cout<<&quot;p1>p2&quot;<<endl; Присвоєння p1 = p2; p1 =&x; p1 = new float(3); char *pc = new char [ 100 ] ;  Збільшення, зменшення p1++; ++p1; p1--;--p1; p1+10; p1-10; cout<<p2+1; //0x004418F4
Відсилка (псевдонім) ( reference ) Відсилка або псевдонім — це альтернативне ім’я об’єкта, яке позначає об’єкт на рівних правах з його основним іменем. При створенні псевдонім зв'язується зі своїм об'єктом (відсилає до нього) і ця відсилка дійсна протягом усього життя псевдоніму. Для чого? Для того, щоб у різних частинах програми іменувати одну й ту ж область пам'яті зручним і зрозумілим для цієї частини іменем
Відсилка (псевдонім) ( reference ) float x = 1.024; //визначення змінної х float &xRef = x; //визначення її псевдоніму xRef *= 2; // x == xRef == 2.048
Копіювання float x = 1,024; //визначення змінної x float xCopy = x; //визначення її копії xCopy += x; //подвоєння xCopy, x незмінний
Відсилка і указник float x = 1,024; //визначення змінної х float *px = &x; //визначення указника на неї
Відсилка і указник px = new float(3.33333); // x == 1,024; *px == 3.33333 //Зв’язок між px і x розірвано
Відсилка і указник Указнику  p  відповідає два елементи пам'яті, кожен з яких має власне значення. Зміна значення  p  розриває наявний зв’язок між елементами пам'яті ,  наприклад,  px = 0;
Відсилка і сталий указник float x = 1.024; //визначення змінної х float *const px = &x; //сталий указник на неї //схожість: зв’язок нерозривний //відмінність: наявність двох елементів пам'яті
Стала відсилка const float pi = 3.14159; const float &piRef = pi;
Стала відсилка Що б це значило? float x = 1; const float& rx = x; x =2; cout<<rx<<endl; Якщо псевдонім сталий, то він не має права змінити об'єкт, але безпосередня зміна об'єкту, якщо він не сталий можлива
Указники указників double **ppd = new double*; *ppd = new double(5); cout<<ppd<<endl; cout<<*ppd<<endl; cout<<**ppd<<endl; Використання указників на указники  ― р озповсюджена техніка програмування у “чистому” С. Проблеми управління пам'яттю при цьому зростають, бо необхідно слідкувати за обома поверхами указника. Вживати ще обережніше, ніж звичайні.

03 Constants And Variables

  • 1.
    Бублик Володимир ВасильовичПрограмування - 2 Лекція 3. Базові поняття програмування. Сталі та змінні Лекції для студентів 2 курсу
  • 2.
    Літерали Літерал (з латинського literal — буквальний) — це найпростіший об’єкт, що позначає сам себе. Цілі літерали 100 //десятковий запис 0144 //вісімковий ( o ctal ) 0х64 //шістнадцятковий ( hexadecimal , he x ) Вісімковими і шістнадцятковими константами варто користуватися лише для типів без знаку, інакше на комп’ютерах з доповняльним кодом можна зіткнутися із несподіванками типу значення –1 для константи 0xffffffff
  • 3.
    Літерали Уточнення типу числового літералу U, L або UL 2147483648U 2147483648L 2147483648UL F або L 1.0F 3.1415926535897932 L
  • 4.
    Літерали Символьні літерали // звичайні символи ’ ?’, ’f’, ’ї’
  • 5.
    Літерали Символьні літерали // вісімкові коди ’ \77’ // символ ’?’ ’ \144’ // символ ’f’ ’ \365’ // символ ’ї’ ( з точністю до кодової таблиці ) ’ \11’ // символ табуляції ’ \12’ // символ нового рядка ’ \14’ // символ нової сторінки
  • 6.
    Літерали Символьні літерали // шістнадцяткові коди ’ \x3f’ // символ ’?’ ’ \x66’ // символ ’f’ ’ \x10’ // символ нового рядка
  • 7.
    Літерали Символьні літерали // службові символи ’ \t’ // символ табуляції ’ \n’ // символ нового рядка ’ \f’ // символ нової сторінки Як бачимо, деякі з символів можна записати різними рівносильними способами: ’ \x10’, ’\12’ і ’\n’ ’ f’, ’\144’ і ’\x66’
  • 8.
    Літерали Багатосимвольні літерали (рядки) ” A” // послідовність, складена з ’A’ і ’\0’ ″ Це константа, складена із символів″ ” This is another string” ” Наступний рядок містить службові символи” ” \n№п/п\tНазва\tКількість\n” Виведеться як № п/п Назва Кількість
  • 9.
    Літерали vs. Іменовані об'єкти Літерали не потребують визначення, бо позначають самі себе, а запис літералу однозначно визначає його тип. Іменовані об'єкти вимагають попереднього визначення (створення) або оголошення . Визначення і оголошення визначають ім'я і тип об'єкту. Визначення приводить до створення об'єкту в пам'яті , тоді як оголошення посилається на об'єкт, створений в іншому місці. Визначення звичайно суміщують з ініціалізацією.
  • 10.
    Визначення сталих const float pi = 3.14159; const float Avogadro =6.02252e23; const double dpi = 3.141592653589793; const char tab = ‘\t’; const char title[] = ”C++ Programming Language”; const int sample; // сталу необхідно визначити! const int sample = 1756; sample = 456; // значення сталої не можна змінити!
  • 11.
    Визначення змінних inti= 1 , j= 1 , k= 1 ; // добре unsinged long counter= 0 ; // змінні корисно ініціювати double a = 0.0 , b= 1.0 ; double eps = 0.000001 ; double x; //визначення з наступним присвоєнням x = 0; //чому не ініціалізація double x = 0; ? double x; //не годиться! Перше присвоєння надто ………… .. x = 0; // далеко від визначення
  • 12.
  • 13.
    Арифметичне присвоєння x= e; де x – іменуючий вираз, e – арифметичний вираз Обчислити lvalue (x) Обчислити rvalue (e) Переслати rvalue (e) до lvalue (x) Значенням виразу x = e вважати нове значення value (x) Яке з них lvalue чи rvalue ? ― Залежно від контексту
  • 14.
  • 15.
  • 16.
  • 17.
    Приклади присвоєнь s= pi * r * r; i = j+k; Суміщене присвоєння i += k; // i = i+k i >>= k; // i = i>>k Інкремент (декремент) постфіксний // нехай k==1 j=k++ //j=k; k=k+1; // j==1; k==2 (i=++(j=++k))++ ; ??? префіксний // нехай k==1 j=++k //k=k+1; j=k; // j==2; k==2
  • 18.
    Композиція присвоєнь u= v = w; читається як u = ( v = w ) ; rvalue (w) ―› lvalue (v) rvalue (v) ―› lvalue (u) (u = v) = w; rvalue (v) ―› lvalue (u) rvalue (w) ―› lvalue (u) // що б це значило?
  • 19.
    Зведення типів 1.С (старомодне) week ―› int int (monday) або (int) Monday int ―› week (week) i 2. С++ (новітнє) const_cast, dynamic_cast, static_cast y = static_cast<double>( x ); Дуже обережно! Може з'явитися багато проблем
  • 20.
    Указник ( pointer)int * ptrI; float *px, y, z; float *px, *py, *pz; Визначення без ініціалізації приводять до заповнення пам'яті сміттям. Засмічені указники ( dangling pointer) небезпечні ! float x, *px; сміття сміття некоректні дані некоректна адреса
  • 21.
    Pointer vs. gotoУказники приводять до тих же проблем в структурах даних, до яких приводять оператори переходу в структурах керування. Скрізь, де можна, уникаємо указників. Якщо вживаємо, то дотримуємось суворої дисципліни! Якщо значення указника невідоме, ініціалізуємо його нулем float *px = 0; Якщо значення указника не нуль, то з ним зв'язані два елементи пам'яті!
  • 22.
    Адресування і розіменуванняx=0.25; px = & x; & одномісна операція адресування lvalue(px) rvalue(px) == lvalue (x) == rvalue(&x)
  • 23.
    Адресування і розіменуванняВзаємна оберненість операцій над пам'яттю &(*px) == px px == *(&px)
  • 24.
    Адресування і розіменуванняcout<< * px; * одномісна операція розіменування rvalue(px) == lvalue(x) rvalue(*px) == rvalue(x)
  • 25.
    Динамічне виділення пам'ятіfloat *p = new float; new операція виділення нового елемента пам'яті, його адреса зберігається в p, значення *p заповнено сміттям px = new float; if (px == 0) // вільної пам’яті немає сміття
  • 26.
    Динамічне виділення іініціалізація пам'яті float *p = new float(0.333333); Тепер значення *p коректне
  • 27.
    Правило гарного тонуЯкщо ви виділили динамічну пам’ять за допомогою команди new не забудьте своєчасно звільнити її командою delete та обнулити указник float *p = new float(0.333333); // робіть все, що вам потрібно delete p; p = 0 ;
  • 28.
    Звільнення памяті double*pd = new double(5.2); cout<<pd<<endl; // 0 x00 4419 B0 cout<<*pd<<endl; //5.2 delete pd; cout<<pd<<endl; // 0 x00 4419 B0 cout<<*pd<<endl; //-1.45682e+144 double *n ew_ pd = new double; cout<<n ew_ pd<<endl; // 0 x00 4419 B0 cout<<*pd<<endl; //-6.27744t+066 cout<<*n ew_ pd<<endl;
  • 29.
    Звільнення памяті double*pd = new double(5.2); cout<<pd<<endl; // 0 x00 4419 B0 cout<<*pd<<endl; //5.2 delete pd; // Правило гарного тону pd = 0;
  • 30.
    Сталі величини іуказники Указник сталої const float pi = 3.14159; const float *piPtr = &pi ; //*piPtr = 4; ERROR!
  • 31.
    Сталі величини іуказники float x = 1; const float* px = &x; x =3; cout<<*px<<endl; //*px = 4; як і раніше ERROR! Указник сталої не має права змінити об'єкт, але безпосередня зміна об'єкту, якщо він не сталий можлива
  • 32.
    Сталі величини іуказники Сталий указник float x = 0.25; float *const px = &x ; //px = &y; ERROR!
  • 33.
    Сталі величини іуказники Сталий указник сталої const float pi = 3.14159; const float *const piPtr = &pi ; //*piPtr = 4; ERROR! //piPtr = &nAvogadro; ERROR!
  • 34.
    Безтипові указники void*voidPtr; //Що б це значило? voidPtr char * str “ \nabcdefghij” 00 A0 69 68 67 66 65 64 63 62 61 0 A
  • 35.
    Безтипові указники void*voidPtr; //Що б це значило? voidPtr Якби це був Бейсик “ abcdefghij” 00 A0 69 68 67 66 65 64 63 62 61 0 A
  • 36.
    Безтипові указники void*voidPtr; //Що б це значило? voidPtr short int * i 24842 A0 00 69 68 67 66 65 64 63 62 61 0 A
  • 37.
    Безтипові указники void*voidPtr; //Що б це значило? voidPtr float * x 4.17596e+021 A0 00 69 68 67 66 65 64 63 62 61 0 A
  • 38.
    Безтипові указники void*voidPtr; //Що б це значило? voidPtr int * k 1667391754 A0 00 69 68 67 66 65 64 63 62 61 0 A
  • 39.
    Безтипові указники void*voidPtr; //Що б це значило? float *pf = new float(3.1); double *pd = new double(5.2); voidPtr = pf; cout<<voidPtr<<endl; // 0 x00 4419 F0 // cout<<*voidPtr<<endl; розіменування неможливе voidPtr = pd; cout<<voidPtr<<endl; // 0 x00 4419 B0
  • 40.
    Символьний указник char*c = new char; cout<<*c<<endl; char *cc = new char('a'); cout<<*cc<<endl; // char *str = new char(“String?“); char *str = &quot;Operation New is not needed&quot;; cout<<str<<endl;
  • 41.
    Операцій над указникамиfloat *p1=new float(1), *p2=new float(2); cout<<p2; //0x004418F0 Порівняння на рівність або нерівність p1 == p2; p1 > p2;… if(p2>p1) cout<<&quot;p2>p1&quot;<<endl; else cout<<&quot;p1>p2&quot;<<endl; Присвоєння p1 = p2; p1 =&x; p1 = new float(3); char *pc = new char [ 100 ] ; Збільшення, зменшення p1++; ++p1; p1--;--p1; p1+10; p1-10; cout<<p2+1; //0x004418F4
  • 42.
    Відсилка (псевдонім) (reference ) Відсилка або псевдонім — це альтернативне ім’я об’єкта, яке позначає об’єкт на рівних правах з його основним іменем. При створенні псевдонім зв'язується зі своїм об'єктом (відсилає до нього) і ця відсилка дійсна протягом усього життя псевдоніму. Для чого? Для того, щоб у різних частинах програми іменувати одну й ту ж область пам'яті зручним і зрозумілим для цієї частини іменем
  • 43.
    Відсилка (псевдонім) (reference ) float x = 1.024; //визначення змінної х float &xRef = x; //визначення її псевдоніму xRef *= 2; // x == xRef == 2.048
  • 44.
    Копіювання float x= 1,024; //визначення змінної x float xCopy = x; //визначення її копії xCopy += x; //подвоєння xCopy, x незмінний
  • 45.
    Відсилка і указникfloat x = 1,024; //визначення змінної х float *px = &x; //визначення указника на неї
  • 46.
    Відсилка і указникpx = new float(3.33333); // x == 1,024; *px == 3.33333 //Зв’язок між px і x розірвано
  • 47.
    Відсилка і указникУказнику p відповідає два елементи пам'яті, кожен з яких має власне значення. Зміна значення p розриває наявний зв’язок між елементами пам'яті , наприклад, px = 0;
  • 48.
    Відсилка і сталийуказник float x = 1.024; //визначення змінної х float *const px = &x; //сталий указник на неї //схожість: зв’язок нерозривний //відмінність: наявність двох елементів пам'яті
  • 49.
    Стала відсилка constfloat pi = 3.14159; const float &piRef = pi;
  • 50.
    Стала відсилка Щоб це значило? float x = 1; const float& rx = x; x =2; cout<<rx<<endl; Якщо псевдонім сталий, то він не має права змінити об'єкт, але безпосередня зміна об'єкту, якщо він не сталий можлива
  • 51.
    Указники указників double**ppd = new double*; *ppd = new double(5); cout<<ppd<<endl; cout<<*ppd<<endl; cout<<**ppd<<endl; Використання указників на указники ― р озповсюджена техніка програмування у “чистому” С. Проблеми управління пам'яттю при цьому зростають, бо необхідно слідкувати за обома поверхами указника. Вживати ще обережніше, ніж звичайні.