Оператори - прв дел

Операнд претставува дел од израз врз кој се вршат акции (операции). Во C++, операнди се константите (3, 5, 3.14, "string"), променливите и функциите кои враќаат вредност. Оператори се делови од изразите кои кажуваат какви операции треба да се извршат врз операндите - се со цел да се добие некаков резултат. На пример, во изразот "1+5" - 1 и 5 се операнди, а '+' (плус) е оператор. Операторот за собирање '+' кажува како да се искомбинираат операндите (1 и 5) за да се добие нова вредност (6).

Во С++, најчесто се користат следните два типа на оператори:

  • унарни оператори - оператори кои вршат акции врз еден операнд. Наједноставен пример за унарен оператор е '-' операторот, кој може (на пример, во изразот -155) да изврши акција врз еден операнд (155) и да произведе нова вредност (-155).
  • бинарни оператори - оператори кои вршат акции врз два операнди. На пример, во изразот "3+5", операторот '+' претставува бинарен оператор.

Некои оператори, зависно од контекстот во кој се наоѓаат, може да се искористат во унарни операции (-5), но и во бинарни операции (10-5).

Доделување на вредност (=)

Една променлива може, во различни временски периоди, да се користи за чување на различни вредности. Во C++, вредности на променливите им се доделуваат со примена на операторот '='. На пример, со изразот "prom=1000;" и се доделува вредност 1000 на променливата prom. Запаметете, во C++, доделувањето на вредности се извршува од десно на лево (вредноста која се наоѓа од десна страна на операторот '=' и се доделува на променливата која се наоѓа од лева страна на операторот). Обратното не важи - вредноста на променливата која се наоѓа од левата страна на операторот не влијание, на никаков начин, на вредноста на изразот кој се наоѓа од десната страна на операторот. На пример, со изразот "a=b;" на променливата a и ја доделуваме вредноста која до тој момент се наоѓала во променливата b. Променливата b си ја задржува својата вредност.

Многу важно е да забележиме дека со операторот '=' се врши доделување на вредност, а не поврзување на изразите кои се наоѓаат од двете страни на операторот. На пример, по извршување на операцијата за доделување на вредност "a=b;", променливите a и b, на ниту еден начин, не се поврзани една со друга. Евентуалната промена на вредноста на променливата b подолу во програмата нема да предизвика и промена на вредноста на променливата a:

Програма 8.1

#include <iostream>
using namespace std;

int main()
{
      int a, b, c;
      a = 100;                             //a=100     b=*    c=*
      b = 50;                              //a=100     b=50   c=*
      c = 20;                              //a=100     b=50   c=20
      
      a = b;                               //a=50      b=50   c=20
      b = 30;                              //a=50      b=30   c=20
      
      c = b;                               //a=50      b=30   c=30
      
      a = b+c;                             //a=60      b=30   c=30
      
      cout << "a=" << a << endl;           //pechati  'a=60'
      cout << "b=" << b << endl;           //pechati  'b=30'
      cout << "c=" << c << endl;           //pechati  'c=30'
      
      return 0;
}

Едно интересно својство на операторот за доделување на вредност '=' е што неговото извршување резултира со враќање на вредноста која се наоѓа од десната страна на изразот. На пример, по извршување на наредбата "a=b=c=10;" сите три променливи (a, b и c) ќе ја содржат вредноста 10 (c=10 враќа резултат 10; потоа b=c=10 враќа резултат 10). Ова својство може да се искористи и во многу посложени пресметки. На пример, наредбата "a=b+(c=10+5);" е еквивалентна (има ист ефект) со извршувањето на двете наредби "c=10+5;" и "a=b+c;" - наведени последователно. По извршување на наредбата "a=3+(c=10+5);", променливата c ќе содржи вредност 15 (c=10+5), додека a ќе содржи вредност 18 (a=3+15).

Програма 8.2

#include <iostream>
using namespace std;

int main()
{
      int a, b, c;
      a = b = c = 10;                   //a=10    b=10    c=10
      
      a = a+5;                          //a=15    b=10    c=10
      
      c = b + (a=10);                   //a=10    b=10    c=20
      
      a = b = c = 0;                    //a=0     b=0     c=0
      
      a = b = c+5;                      //a=5     b=5     c=0
      
      a = b = (c=10);                   //a=10    b=10    c=10
      
      cout << (a+b+c) << endl;          //pechati '30'
      
      return 0;
}

Аритметички оператори (+, -, *, /, %)

C++ подржува 5 бинарни аритметички оператори: оператор за собирање (+), оператор за одземање (-), оператор за множење (*), оператор за делење (/) и оператор за пресметка на остаток од делење (%). Следнава табела ги содржи основните информации за гореспоменатите аритметичките оператори:

операција оператор форма
собирање + a+b
одземање - a-b
множење * a*b
делење / a/b
остаток (модул) % a%b

Операциите собирање, одземање и множење го имаат стандардното математичко значење. Доколку операциите (важи за сите аритметички операции) се извршуваат врз операнди од ист тип, резултатот е операнд од истиот тој тип (доколку, во изразот "a+b", а и b се променливи од тип int, и резултатот ќе биде од тип int). Доколку, барем една од променливите е од тип на податок кој овозможува чување на вредности кои се децимални (реални) броеви, тогаш и резултатот ќе биде од тип кој овозможува чување на децимални броеви (доколку, во изразот "a+b", а е променлива од тип int, а b е променлива од тип double, тогаш резултатот ќе биде од тип double). Ова не важи за операторот '%' - тој може да се извршува само врз податоци кои се цели броеви.

Доколку двата податока се цели броеви, тогаш резултатот од извршување на операцијата делење (a/b) ќе биде цел број. На пример, 5/2 ќе врати вредност 2 (иако 5/2 e 2.5). Доколку барем еден од податоците е реален (децимален) број, резултатот од извршувањето на операцијата делење ќе биде реален (децимален) број. На пример, 5.8/2 ќе врати вредност 2.9 (бидејќи операндот 5.8 е реален број). Делење со 0 (или 0.0) не е дозволено.

Операторот '%' може да се примени само врз целобројни податоци. Резултатот од извршувањето на операцијата a%b е остатокот од делењето на бројот a со b. На пример, 10%3 е еднакво на 1 (10/3 e 3, со остатокот 1 - бидејќи 10=3*3 + 1), 25%7 е еднакво на 4 (25/7 е 3, со остаток 4 - бидејќи 25=7*3+4). Операторот '%' најчесто се користи при проверка на тоа дали еден цел број е делив со друг - во тој случај изразот a%b треба да е еднаков на 0 (бидејќи доколку b го дели а, нема да се појави остаток при нивното делење).

Следната програма го демонстрира ефектот на секој од аритметичките оператори споменати погоре:

Програма 8.3

#include <iostream>
using namespace std;

int main()
{
      int a=1, b=2, c=3;            //a=1   b=2     c=3
      
      a=b+c;                        //a=5   b=2     c=3
      a=c-b;                        //a=1   b=2     c=3
      a=b*c;                        //a=6   b=2     c=3
      
      b=10;                         //a=6   b=10    c=3
      c=5;                          //a=6   b=10    c=5
      
      a = b/c;                      //a=2   b=10    c=5
      a = b%c;                      //a=0   b=10    c=5
      
      b=8;                          //a=0   b=8     c=5
      
      a = b/c;                      //a=1   b=8     c=5
      a = b%c;                      //a=3   b=8     c=5
      
      cout << a << endl;            //pechati '3'
      
      return 0;
}

Скратување на изрази (+=, -=, *=, /=, %=, ++, --)

Многу често, се појавува потреба од промена на вредноста на една променлива преку вршење на математичка операција врз истата таа променлива (a=a+5). C++ подржува 5 оператори (по еден оператор за секоја аритметичка операција) кои овозможуваат скратено пишување на горенаведениот тип на операции. На пример, наместо да пишуваме "а=а+5;" сега можеме да напишеме "a+=5;", наместо "a=a*5;" може да напишеме "a*=5;", наместо "a=a/b;" може да напишеме "a/=b;", итн. Следнава табела ги содржи сите потребни информации за овие оператори:

операција израз еквивалентно со
додади b на а a+=b; a = a+b;
одземи b од a a-=b; a = a-b;
помножи го a со b a*=b; a = a*b;
подели го a со b a/=b; a = a/b;
смести го остатокот од a/b во a a%=b; a = a%b;

Зголемувањето на вредност за 1 и намалувањето на вредност за 1 се, исто така, операции кои се извршуваат многу често. И овие операции, во C++, си имаат свој оператор преку кои се дефинирани (++ и --, соодветно). Всушност, постојат две верзии (prefix и postfix) за секој од овие два оператори (++ и --) - зависно од тоа дали операторот се наоѓа пред променливата (++x) или по променливата (x++):

операција израз значење
зголемување на вредност за 1 - postfix верзија x++ врати ја вредноста која се содржи во променливата x, па зголеми го x за 1
зголемување на вредност за 1 - prefix верзија ++x зголеми го x за 1, па врати ја вредноста која се содржи во променливата x
намалување на вредност за 1 - postfix верзија x-- врати ја вредноста која се содржи во променливата x, па намали го x за 1
намалување на вредност за 1 - prefix верзија --x намали го x за 1, па врати ја вредноста која се содржи во променливата x

За едноставни изрази како "x++;" двете верзии (prefix и postfix) ќе резултираат со зголемување/намалување (за 1) на вредноста која се чува во променливата x. Разликата се забележува во случаи кога резултатот од изразот се користи во некоја поголема наредба (како "y=x++;" и "y=++x;"). Во овој случај, двете верзии на операторите се однесуваат на различен начин: prefix верзијата ("y=++x;") прво ја зголемува вредноста на променливата (во случајов x) па го предава резултатот (зголемената вредност), додека postfix верзијата ("y=x++;") создава копија од вредноста на променливата x, ја предава привремената вредност, па дури потоа ја зголемува вредноста на x. На пример, доколку x=5 и ја извршиме наредбата "y=++x;", по извршување на наредбата вредноста на x ќе биде 6 и вредноста на y ќе биде 6 - прво се зголемува x, па потоа се испраќа нејзината "зголемена" вредност. Од друга страна, доколку x=5 и ја извршиме наредбата "y=x++;", вредноста на x ќе биде 6, но вредноста на y ќе биде 5 - најпрвин се прави привремена копија од вредноста на x и таа вредност се доделува на y, па дури потоа се зголемува x. Следнава програма го демонстрира ефектот на неколку оператори споменати во овој дел:

Програма 8.4

#include <iostream>
using namespace std;

int main()
{
      int a=10, b=15, c=20;                                  //a=10  b=15    c=20
      a+=b;                                                  //a=25  b=15    c=20
      a+=b;                                                  //a=40  b=15    c=20
      a+=b;                                                  //a=55  b=15    c=20
      
      a-=c;                                                  //a=35  b=15    c=20
      b*=c;                                                  //a=35  b=300   c=20
      
      a+=(b+c);                                              //a=355 b=300   c=20
      
      b+=b;                                                  //a=355 b=600   c=20
      
      c++;                                                   //a=355 b=600   c=21
      c--;                                                   //a=355 b=600   c=20
      
      a = c++;                                               //a=20  b=600   c=21
      a = c--;                                               //a=21  b=600   c=20
      
      a = ++c;                                               //a=21  b=600   c=21
      
      cout << a << " " << b << " " << c << endl;             //pechati '21 600 21'
      
      //pred izvrshuvanje  a=21 b=600  c=21
      cout << a++ << " " << b-- << " " << c++ << endl;       //pechati '21 600 21'
      //po izvrshuvanje  a=22   b=599  c=22
      
      //pred izvrshuvanje  a=22   b=599  c=22
      cout << ++a << " " << --b << " " << ++c << endl;       //pechati '23 598 23'
      //po izvrshuvanje  a=23   b=598  c=23
      
      return 0;
}

Операции со битови (<<, >>, ~, &, |, ^ и <<=, >>=, |=, &=, ^=)

Во C++ постојат оператори кои вршат акции (операции) врз битовите на една променлива. Следнава табела содржи информации за 6-те вакви оператори:

операција израз значење
поместување во лево x << n помести го секој бит во x - n места налево
поместување во десно x >> n помести го секој бит во x - n места надесно
НЕ (NOT), бит по бит ~x промени ги сите битови во x (1 станува 0, а 0 станува 1)
И (AND), бит по бит x & y операција И (AND) помеѓу сите битови од x и y кои се наоѓаат на иста позиција
ИЛИ (OR), бит по бит x | y операција ИЛИ (OR) помеѓу сите битови од x и y кои се наоѓаат на иста позиција
исклучиво ИЛИ (XOR), бит по бит x ^ y операција XOR помеѓу сите битови од x и y кои се наоѓаат на иста позиција

Унарниот операторот '~' врши промена (1 станува 0, а 0 станува 1) на сите битови од кои е составен операндот врз кој се извршува. На пример, промената на битови кај бројот 153 (бинарно 10011001) ќе резултира со вредноста 01100110 (декадно 102). Забележете како сите битови ја променија својата вредност - единиците станаа нули, а нулите станаа единици. За да ги претставиме работите полесно, во сите примери ќе работиме со 8 бита. Нормално, точниот резултат ќе зависи од тоа колку битови има податочниот тип со кој е дефинирана променливата врз која вршиме одредена операција. На пример, доколку x беше променлива од тип unsigned int (кој има големина од 4 бајти = 32 бита), повикувањето на ~x кога x=153 (00000000 00000000 00000000 10011001) ќе резултираше со вредноста 11111111 11111111 11111111 01100110, што е еднакво на 4294967142 (преставено декадно).

Операторот '<<' врши поместување во лево на битовите кои се наоѓаат во операндот од левата страна (x) онолку пати колку што изнесува вредноста на операндот од десната страна (n). На пример, поместување на 153 (бинарно 10011001) во лево за 1 (153 << 1) резултира со вредноста 00110010, што е еднакво на 50 (декадно). Забележете како сите битови се поместија еден чекор на лево. Поместување во лево за 3 на истата вредност (153 << 3) резултира со вредноста 11001000. Сега, сите битови се поместија во лево за 3. Забележете дека, при поместување во лево, битовите кои се наоѓаат најлево (најзначајните битови) се губат и не доаѓаат од десна страна - таму доаѓа 0.

Операторот '>>' врши поместување во десно на битовите кои се наоѓаат во операндот од левата страна (x) онолку пати колку што изнесува вредноста на операндот од десната страна (n). На пример, поместување на 153 (бинарно 10011001) во десно за 1 (153 >> 1) резултира со вредноста 01001100, што е еднакво на 76 (декадно). Сите битови се поместија еден чекор во десно. Битовите кои се наоѓаат најдесно (најнезначајните битови) се губат и не доаѓаат од лева страна - таму доаѓа 0.

Освен сличниот начин на запишување ('>>' и '<<'), не постои никаква поврзаност помеѓу операторите за поместување на битови и операторите за читање на податоци од тастатура (cin >> x;) или печатење на податоци на екран (cout << x;).

Операторите '&', '|' и '^' вршат операции врз сите битови од кои се составени операндите од нивната лева и десна страна (бит по бит). Операцијата И (AND) враќа вредност 1 единствено доколку двата бита врз кои се извршува се 1 (во спротивно, враќа вредност 0). Операцијата ИЛИ (OR) враќа вредност 1 кога барем еден од двата бита е 1. Операцијата XOR враќа вредност 1 кога точно еден (само еден) од двата бита има вредност 1:

бит 1 бит 2 И (AND) ИЛИ (OR) XOR
0 0 0 0 0
0 1 0 1 1
1 0 0 1 1
1 1 1 1 0

Да ги разгледаме следните 3 изрази: 153&172, 153|172 и 153^172. Операциите најлесно може да ги разбереме доколку ги запишеме двата операнди еден до друг. Откога ќе го направиме тоа, потребно е да ја извршиме соодветната операција на секоја колона:

10011001 (153)
&&&&&&&&
10101100 (172)
========
10001000 (136)

Значи, 153&172 е еднакво на 136. Забележете дека операцијата И (AND) ја спроведовме врз секој пар од битови (за секоја колона посебно).

Да продолжиме понатаму - со разгледување на вредноста на изразот 153|172.

10011001 (153)
||||||||
10101100 (172)
========
10111101 (189)

Значи, 153|172 е еднакво на 189. Повторно, операцијата ИЛИ (OR) ја спроведовме врз секој пар од битови.

10011001 (153)
^^^^^^^^
10101100 (172)
========
00110101 (53)

Значи, 153^172 е еднакво на 53. Овие операции може да се спроведат и врз повеќе операнди (на пример, 153&192&58). Во тој случај, кај операцијата И (AND) битовите во една колона ќе бидат 1 ако и само ако сите битови во таа колона се 1, кај ИЛИ (OR) битовите во една колона ќе бидат 1 ако најмалку еден од битовите во таа колона е 1, додека кај XOR битовите кај една колона ќе бидат 1 доколку постојат непарен број на единици во таа колона.

Операторите кои ги спомнавме погоре се користат многу ретко. Порано, кога компјутерите беа побавни и содржеа многу помалку меморија, беше важно да се искористи секој бит од меморијата. Денес, многу поважно од неколку мегабајти меморија е програмата да е лесно разбирлива.

Добар пример за можностите кои ги нудат операторите споменати погоре е податочниот тип bool - кој користи меморија од 1 бајт (тоа е најмалиот можен дел кој може да се адресира) за чување на податоци за кои е потребен само 1 бит (точно/неточно). Останатите 7 битови не се користат (пропаѓаат). Со користење на операторите споменати погоре е можно да се чуваат 8 bool вредности во 1 бит (со соодветно поместување).

Покрај ова, операторите & (AND) и | (OR) може да се искористат за вршење на операциите пресек и унија. Доколку две променливи (a и b) од тип int ги користат своите 32 бита за претставување на множества (со 32 бита може да се чуваат информации за 32 елементи - 1 ако елементот се наоѓа во соодветното множество, или 0 ако не се наоѓа). За вака дефинирани променливи, a&b го означува пресекот на овие две множества (кај елементите кои се наоѓаат во двете множества, битот треба да е 1), додека a|b ја означува унијата (кај елементите кои се наоѓаат во барем едно од двете множества, битот треба да е 1).

За крај, да наведеме дека слично како аритметичките оператори, операторите '<<', '>>', '&', '|' и '^' можат да се употребат и во скратена форма (за менување на вредност на одредена променлива). На пример, наместо да пишуваме "x = x << 3;" можеме да запишеме "x <<= 3;". Следнава табела содржи информации за операторите '<<=', '>>=', '&=', '|=' и '^=':

операција израз еквивалентно со
помести го секој бит во a, n места налево a<<=n; a = a<<n;
помести го секој бит во a, n места надесно a>>=n; a = a>>n;
во а смести го резултатот од операцијата И (AND) помеѓу сите битови од a и b кои се наоѓаат на иста позиција a&=b; a = a&b;
во а смести го резултатот од операцијата ИЛИ (OR) помеѓу сите битови од a и b кои се наоѓаат на иста позиција a|=b; a = a|b;
во а смести го резултатот од операцијата XOR помеѓу сите битови од a и b кои се наоѓаат на иста позиција a^=b; a = a^b;

Во следното предавање ќе разгледаме уште неколку оператори. Дополнително, ќе споменеме кои оператори имаат предност при пресметување на изрази од типот "x=5+3*3;".

Дозвола за користење: CC BY-NC 2.5 ©