FizWeb

Porkoláb Zoltán - C programozás 2017.10.09. előadás jegyzet

4. előadás: Operátorok, kifejezések, kifejezések kiértékelése, precedenciák

X = A*B/C*D
Y = A+B*C

--> C-ben operátorok, Fortranban ezek utasítások (nem kell ;)

Az azonos precedenciájú műveletek sorrendje?? (Fortranban nem gondoltak rá)
--> ma ált. balról jobbra (pl. Java)

pl.:
! * ++ *p
//ezt így zárójelezem: (assziciativitási szabály)
!(*(++(*p)))

Különféle operátorok:

1. precedenciaosztály:
// index: [] pl. t[i] --> 2 param.
// record (struct): pl. r.m

    struct hallgato  //ez egyféle hallgato típusú változó
    {
      char neptun[6];
      char nev[20];
      int kor;
    };

    struct hallgato Bela, Dezso;
    (Bela.neptun[0] ...)

//pointerrel
(*ptr).kor  //kell a (), mert a * alacsonyabb precedenciájú
ptr->kor    //rövidítés

// függvényhívás ()
sin(.5)

  [],(),* szerencsére (köszi Ritchie) kifejezés, nem pedig spec utasítás

// postfix
i--
i++
//i értéke nem változik, pl.
int i=1;
int k=i++; //itt k=2, i=1 marad

2. osztály:

//negáció: 0 --> 1; nem0 --> 0
!a
//bitenkénti negálás (op.rendsz): 0 --> -1; -1 --> 0; más nem 0 --> más nem 0
~a

//prefix
++i
--i
//pl.
int i = 1;
int k = ++i; //itt k==2 & i==2
//i=i++ veszélyes lehet, újabb függvényhívásnál más értékkel számol--> nem olyan átlátható

C: hardware-közeli elemek elérése
pl. pointer: címre vonatkozó hivatkozás
&a //címoperátor  (itt van az a)
*p //dereferencia (ezen a helyen az "a" van)

3. osztály:
a*b //szorzás
a/b //osztás
a%b //modulo

4. osztály:
a+b
a-b

5. osztály:
a<>b
//shift operátor: lineáris eltolás, 2^b-nel szoroz
pl. 5<<2 binárisan: 000...0101  ->   0...010100 (felül elvesznek bitek, elveszhet az előjel v. értékes jegy)
5<<-2 undefined, helyette 5>>2: ->   0...000001

6. osztály:
ab
a<=b  a>=b

7. osztály:
a==b  a!=b

8. osztály:
&

9. osztály:
^ //bitenkénti XOR

10. osztály:
| //-> 0-t VAGY 1-t ad

11. osztály:
&& //logikai ÉS

12. osztály:
|| //logikai vagy

13. osztály:
a ? b : c

14. osztály:
a = (b = c) //értékadás: ez is kifejezés!
a+=b
a-=b
a%=b

15. osztály:
a, b //vessző
________________________

pl. tudni szeretném h mi van X utolsó bájtjában:
x&0xff == 12
Ritchie: hiba volt az ==-t feljebb rakni
Itt: először xff==12 értékelődik ki -> 0/hamis
x&0 -> mindig hamis
mindig zárójel kell: (x&0xff)==12

logikai ÉS/VAGY: rövidzáras műveletek (shortcut), pl.:
am < 19;
a!=b || b!=c //Pascal: mindkét oldalt kiértékelné

a ? b : c
pl.
# define MAX(a,b) ((a)>(b)?(a):(b))
z=MAX(3*x,f());
--> lehetne if-else párral (néha így egyszerűbb)

értékadás:
a=b //ennek a akifejezésnek az értéke: "a" új értéke
//ez is értelmes:
c = (a=b) + 3
*p=b //pl. C++-ban nagy haszon

int ch;
while ((ch=getchar()) != EOF) { //az stdio.h-ban egy macro
  /* code */
}

BALÉRTÉK:
ami értékadás bal oldalán állhat (írható tárterületet def.)
összes többi: jobbérték
pl. sin()
a = b = c //megfelelő sorrend
a+=b //rövid és a-t csak egyszer értékeli ki
vs.: a = a+b

_______________________________________

Ennyi lenne szemantika szempontjából.
DE: futási idő!

int f() {
  printf("f");
  return 2;
}

int g() {
  printf("g");
  return 1;
}

int h() {
  printf("h");
  return 0;
}

int main() {
  printf("%d\n", f()==g()==h() );
}

//2==1 -> hamis/0
//-> 0==0 -> igaz
//ez kiírja az egyet, meg előtte még 3 betűt --> Milyen sorrendben? A fordítótól függ (optimális ford.).
________________________

tipikus hiba:

int t[10];
int i=0;
while (i<10) {
  t[i] = i++;
}

BAJ: i++-t kiértékelem -> elején 0, végén 9, DE: nem tudhatom h a t[i] hányadik elem

while (i<10) {
  t[i] = i;
  i++;
}
--> ezzel nincs baj, mivel {; && || ,} szekvenciapont -> azelőtti biztosan kiértékelődik, mielőtt továbblép
_______________________________________
Összefoglalva:

1. precedencia
2. asszociativitás
3. balérték
4. fordítási sorrend (-> nem tudom meghatározni)