Bitműveletek, hatékony programok írása. Pointer, pointer tömb kapcsolat Flashcards
Mik a bitműveletek?
Ezek olyan műveletek, amiket bit szinten lehet végezni. A byte műveletekhez hasonlóan (&&, ||) a bitműveletek bemenő paramétere is legalább 1 byte méretű, hiszen 1 byte a legkisebb méret, amivel memóriaterületet lehet lefoglalni. A C-ben található bitműveletek megtalálhatók C++ nyelvben is.
példa program a bitműveletekre.
deklaráció.
#include using namespace std;
int main() { Két változó: a és b, decimálisan és binárisan. unsigned int a = 60; // 60 = 0011 1100 unsigned int b = 13; // 13 = 0000 1101 int c = 0;
példa program a bitműveletekre.
&
Az első bitművelet a & (bitwise AND). a két szám ugyanazon helyiértéken (bináris helyiértéken) lévő bitje 1, akkor az & operátor is 1-et ad vissza. Ezáltal láthatjuk, hogy a & b = 0000 1100.
c = a & b; // 12 = 0000 1100
cout «_space;“Line 1 - Value of c is : “ «_space;c «_space;endl ;
példa program a bitműveletekre.
|
A | (bitwise OR) művelet hasonlít az előbbi &-hez, viszont itt elég ha az egyik bit 1, akkor a | művelet már 1-et ad vissza.
c = a | b; // 61 = 0011 1101
cout «_space;“Line 2 - Value of c is: “ «_space;c «_space;endl ;
példa program a bitműveletekre.
^ (xor)
A ^ (bitwise XOR) magyarul kizáró vagy művelet akkor ad vissza 1-et, ha a két változó azonos helyiértékein csak az egyik változó esetén van 1.
c = a ^ b; // 49 = 0011 0001
cout «_space;“Line 3 - Value of c is: “ «_space;c «_space;endl ;
példa program a bitműveletekre.
~ (not)
A ~ (bitwise not). Bitenként nézi meg és állítja át az ellentétes értékre az összes bitet. (ha megkérdezik, hogy az hogy lett -61, akkor azt kell mondaNI, hogy a gép csinálta így).
c = ~a; // -61 = 1100 0011
cout «_space;“Line 4 - Value of c is: “ «_space;c «_space;endl ;
példa program a bitműveletekre. «_space;left shift
A «_space;(left shift) művelet annyit csinál, hogy eltolja bemenő parméternyilvel a biteket bal irányba, tehát 0011 1100-ból 1111 0000 lesz. Egy eltolás kettővel való szorzásnak felel meg, tehát ha kettővel toljuk el, akkor 4-szeres szorzás lesz az eredmény. 4*60 = 240.
c = a «_space;2; // 240 = 1111 0000
cout «_space;“Line 5 - Value of c is: “ «_space;c «_space;endl ;
példa program a bitműveletekre. A»_space; right shift
A»_space; (right shift) művelet ugyanaz, mint a left shift, csak osztással.
c = a»_space; 2; // 15 = 0000 1111
cout «_space;“Line 6 - Value of c is: “ «_space;c «_space;endl ;
return 0;
}
Miért hasznosak számunkra a bitműveletek? Egy példát mutass.
Példa: két szám átlaga osztás művelet nélkül. #include using namespace std; int floorAvg(int x, int y) { return (x + y) >> 1; } int main() { cout<< floorAvg(13,28 ); return 0; }
Milyen változókon tudnak műveleteket végrehajtani a bitműveletek? Ebből mi következik?
short, long, int vagy char, ezért páratlan összeg esetén nem kapunk pontos átlagot, de ez a verzió egész számok esetén gyorsabb, mint ha az osztás operátort használnánk. Ugye itt annyi történik, hogy a két számot összeadjuk, utána 1-gyel eltoljuk balra a biteket (tehát 2-vel osztunk).
mik a pointerek c++-ban? Mi kell a deklarálásukhoz?
C++-ban minden változó a memóriában tárolódik, egy memória cím alatt. A változó értéke ezen a memória címen van tárolva. A pointer egy olyan változó, ami egy másik változó memória címét tárolja. Deklarálása a * (pointer to operator) operátorral történik. Mivel a c++ egy statikusan típusos nyelv, ezért a deklaráláshoz kell egy típus is. Pl:
int *numberPointer;
mit csináltunk azzal, hogy int * numberpointer;?
Inicializáltunk ezzel egy pointert, viszont ez nem mutat sehova, tartalma 0x0. Adhatunk neki viszont értéket, mondjuk egy integer változó memóriacímét.
mire jó az & operátor a pointereknél?
Ezt a & (reference) operátorral tesszük meg. Pl:
numberPointer = &number;
A & operátor az adott változó memória címét adja vissza. Ezzel most már egy változó értékére mutat a pointerünk.
a * operátorral mit lehet még csinálni a pointereknél?
segítségével meg tudjuk változtatni a pointer által azt az értéket, amire mutat. Pl:
*numberPointer = 4;
Mire jók ezek a pointerek?
a függvényt meg lehet írni úgy is, hogy a bemenő paramétere ne egy sima változó legyen, hanem egy pointer. Ez azért jó, mert ilyenkor nem jönnek létre azok az extra változók a függvényhívásoknál, tehát kevesebb memóriát fog használni a programunk. A függvény közvetlenül tudja a változó értékét változtatni.
Alap példaprogram pointerek működésének bemutatására: Deklarálás
#include using namespace std; int main() { Sima változó és pointer deklarálása. (Ezekben még nincs érték) int variable; int *pointerToVariable;
Alap példaprogram pointerek működésének bemutatására: Értékadás az integernek:
Értékadás az integer változónak, értékének és memóriacímének kiiratása.
variable = 5;
cout «_space;“Address of variable (&variable): “ «_space;&variable «_space;endl;
cout «_space;“Value of variable (variable): “ «_space;variable «_space;endl «_space;endl;
Alap példaprogram pointerek működésének bemutatására: Értékadás a pointernek.
Értékadás a pointernek, pointer értékének kiiratása(a memóriacím az értéke),a változó értékének kiiratása, amire a pointer mutat
pointerToVariable = &variable;
cout «_space;“Address that pointerToVariable holds (pointerToVariable): “«_space;pointerToVariable «_space;endl;
cout «_space;“Content of the address pointerToVariable holds (*pointerToVariable): “ «_space;*pointerToVariable «_space;endl «_space;endl;
Alap példaprogram pointerek működésének bemutatására: Integer érték megváltoztatása:
Integer érték megváltoztatása, pointer értékének kiiratása (nem változott, ugyanaz a memóriacím), a változó értékének kiiratása, amire a pointer mutat
(változott)
variable = 11; cout «_space;“Address pointer pointerToVariable holds (pointerToVariable): “ «_space;pointerToVariable «_space;endl;
cout «_space;“Content of the address pointer pointerToVariable holds (*pointerToVariable): “ «_space;*pointerToVariable «_space;endl «_space;endl;
*pointerToVariable = 2; cout << "Address of variable (&variable): " << &variable << endl; cout << "Value of variable (variable): " << variable << endl << endl; return 0; }
A mutatók és a tömbök között milyen kapcsolat áll fenn? Minden művelet ami …
A C++ nyelvben a mutatók és a tömbök között szoros kapcsolat áll fenn. Minden művelet, ami tömbindexeléssel elvégezhető, mutatók segítségével szintén megvalósítható.
Mit tudsz az egycsillagos pointerek, és az egydimenziós tömbök kapcsolatáról? Mit tudsz a többcsillagos pointerek, és a többdimenziós tömbök kapcsolatáról?
Az egydimenziós tömbök (vektorok) és az egyszeres indirektségű („egycsillagos”) mutatók között teljes a tartalmi és a formai analógia. A többdimenziós tömbök és a többszörös indirektségű („többcsillagos”) mutatók esetén ez a kapcsolat csak formai.
honnan származik ez a vektorok és az egyszeres indirektségű mutatók között fennálló szoros kapcsolat? Definiálás.
Definiáljunk egy 5-elemű egész vektort! int a[5]; A vektor elemei a memóriában adott címtől kezdve folytonosan helyezkednek el. Mindegyik elemre a[i] formában hivatkozhatunk (I.17. ábra). Vegyünk fel egy p, egészre mutató pointert, majd a „címe” operátor segítségével állítsuk az a tömb elejére (a 0. elemre)! int *p; p = &a[0]; vagy p = a;
honnan származik ez a vektorok és az egyszeres indirektségű mutatók között fennálló szoros kapcsolat!? mutató beállítása.
A mutató beállítására a tömb nevét is használhatjuk, hisz az is egy int * típusú mutató, csak éppen nem módosítható. (Fordítási hibához vezet azonban a p = &a; kifejezés, hisz ekkor a jobb oldal típusa int ()[5].) Ezek után, ha hivatkozunk a p mutató által kijelölt (p) változóra, akkor valójában az a[0] elemet érjük el.
1.17-es ábra.
https://imgur.com/a/rO6keZP
Mit tudsz a P mutató szerepéről?
teljesen megegyezik az a tömbnév szerepével, hisz mindkettő az elemek sorozatának kezdetét jelöli ki a memóriában. Lényeges különbség azonban a két mutató között, hogy míg a p mutató változó (tehát értéke tetszőlegesen módosítható), addig az a egy konstans értékű mutató, amelyet a fordító rögzít a memóriában.
Hogyan jelölik a tömb i-edik elemét?
A tömb i-dik elemének címe: &a[i] &p[i] a+i p+i A tömb 0-dik eleme: a[0] p[0] *a *p *(a+0) *(p+0) A tömb i-dik eleme: a[i] p[i] *(a+i) *(p+i)
Mit csinál a legtöbb c++ fordító?
az a[i] hivatkozásokat automatikusan (a+i) alakúra alakítja, majd ezt a pointeres alakot lefordítja. Az analógia azonban visszafelé is igaz, vagyis az indirektség () operátora helyett mindig használhatjuk az indexelés ([]) operátorát.