C programozással kapcsolatos vizsgakérdések (16 db)
Bináris fileok
Teljesítménymérés
Programtervezés, kódszervezés
sima C kód optimalizálása CPU-ra
Szám | Kérdés |
---|---|
23. | Ismertesse a veremtár működését! C nyelvű programok futása közben hol van szerepe a veremtárnak? |
35. | Ismertesse a C nyelvű forráskód fordítási és futtatási folyamatát! |
43. | Ismertesse a C nyelv alapvető típusait, tárolási méretükkel! Hol vannak ezek a méretek definiálva (típusonként eltérő)? |
44. | Ismertesse példával a pre- és posztinkrementálás közti különbséget! |
45. | Ismertesse a C nyelv háromoperandusú operátorát! |
46. | Ismertesse a „break” utasítás szerepét a „switch” utasításban! |
47. | Ismertesse példával a C nyelvben alkalmazható bitműveleteket! Miért volt szükség logikai műveletekre a bitműveletek mellett? |
48. | Ismertesse a C nyelv „pointer” fogalmát és az indirekció fogalmát! |
49. | Ismertesse a pointer aritmetikát! |
50. | Ismertesse a tömbök használatánál előforduló komplexitás-típusokat! Mondjon példát arra a műveletre, amelyik adott komplexitású! |
51. | Ismertesse a tömbből való kicímzés veszélyeit! |
52. | Ismertesse a tömbök [] operátorának jelentését! Hogyan írható fel a [] operátor pointer aritmetikát felhasználva? |
54. | Ismertesse a függvények írásának és paraméterezésének nyelvi szabályait a C nyelvben! |
55. | Ismertesse a formális és aktuális paraméter fogalmát a C nyelv függvényeinél! |
56. | Milyen paraméter-átadást használ a C nyelv? Hogyan tudja megváltoztatni a függvény a paraméterei értékét úgy, hogy a hívó folyamatban is a változtatott érték szerepeljen? |
57. | Ismertesse a lokális és globális változó fogalmakat! |
Folyamat | Mit pakolunk a verembe? | Miért fontos? |
---|---|---|
Függvényhívás (call f ) |
– Visszatérési cím – Régi keretmutató – Paraméterek – Caller-save regiszterek |
Így tud a program visszatérni a hívó kódsorára, és megőrizzük a hívó állapotát. |
Lokális (automatikus) változók |
– int x
- char buf[64] stb. |
Élettartamuk csak a függvényhívás idejére szól, ezért ideális őket a veremben tárolni. |
Dinamikus, de rövid életű igény |
– alloca() -val foglalt memória– C99 VLA (változó-méretű tömb) |
Gyorsabb, mint a heap; felszabadul automatikusan a keret kilépésekor. |
Visszatérés (ret ) |
– |
A visszatérési cím kerül az IP-be;
a veremmutató visszaugrik az előző keretre. (IP = Instruction Pointer) |
//Automatikus változók kezelése
void foo(void) {
int a = 5; // a ‘a’ a veremben él
char tmp[100]; // buffer a veremben,
} // kilépéskor a teljes blokk “eltűnik”
Jellemző | Verem (stack) | Kupac (heap) |
---|---|---|
Allokáció | Implicit (utasításokkal) | Explicites: malloc/free, new/delete |
Sebesség | Nagyon gyors (pointer ± Δ) | Lassabb (syscall, lista/algoritmus) |
Méret | Korlátozott (MB-tól tízes MB) | Gyakran a teljes virtuális címtartomány |
Élettartam | Függvényhívás idejéig | Amíg manuálisan fel nem szabadítjuk |
Túlcímzés kockázata | Stack overflow | Memory leak |
Kategória | Típus | ISO C minimum (bit) | Jellemző méret ILP32 (32-bites rendszerek) | Jellemző méret LP64 (klasszikus 64-bites Unix / Linux) |
---|---|---|---|---|
Egész | char / signed char / unsigned char | 8 | 1 bájt | 1 bájt |
short / unsigned short | 16 | 2 bájt | 2 bájt | |
int / unsigned int | 16 | 4 bájt | 4 bájt | |
long / unsigned long | 32 | 4 bájt | 8 bájt | |
long long / unsigned long long | 64 | 8 bájt | 8 bájt | |
Logikai | _Bool | 1* | 1 bájt | 1 bájt |
Lebegőpontos | float | ≥32 | 4 bájt (IEEE-754 single) | 4 bájt |
double | ≥64 | 8 bájt (IEEE-754 double) | 8 bájt | |
long double | ≥64 | 12/16 bájt** | 16 bájt*** | |
Mutató | void*, int*, stb. | — | 4 bájt | 8 bájt |
Típuscsalád | Hol találod a szabványos határokat? | Mire jó? |
---|---|---|
Egészek |
<limits.h> – CHAR_BIT, INT_MAX, LONG_MAX, stb.
|
Fordítási időben megmondják a típus legnagyobb és legkisebb értékét, így közvetve a méretét is (pl. ha INT_MAX = 2 147 483 647 ⇒ 32 bit). |
Lebegőpontos |
<float.h> – FLT_MANT_DIG, DBL_MAX, stb.
|
A mantissza mérete, kitevő tartomány és lekerekítési mód határait adja meg – ezekből következtethetsz a bájt-méretre. |
Rögzített szélességű típusok |
<stdint.h> – int32_t, uint64_t, INT32_MAX, …
|
Csak akkor vannak definiálva, ha az adott pontos szélesség létezik a platformon. |
C11 generikus korlátok |
<stdint.h> – INT_FAST32_MAX, INTPTR_MAX, stb.
|
„Legalább ekkora” vagy „leggyorsabb legalább ekkora” egésztípusok lekérdezése. |
Futás-függő lekérdezés |
sizeof(type) kifejezés
|
Garantáltan fordítási időben számolja ki a tényleges bájt-méretet – hordozható mód. |
#include <stdio.h>
int main(void) {
int a = 5;
int b = ++a; /* pre-increment */
int c = 5;
int d = c++; /* post-increment */
printf("a = %d, b = %d\n", a, b);
printf("c = %d, d = %d\n", c, d);
return 0;
}
//kimenet
a = 6, b = 6
c = 6, d = 5
Elem | Jelentés |
---|---|
Szintaxis |
feltétel ? kifejezés_if_true : kifejezés_if_false
|
Értékelés |
– A feltétel először és pontosan egyszer fut le. – Ha logikailag igaz (≠ 0), a bal oldali kifejezés eredménye lesz az egész kifejezés értéke. – Ha hamis (0), a jobb oldali kifejezés értéke lesz a végeredmény. |
Típus-szabály |
A két „ág” típusát a fordító közös típusra konvertálja
(aritmetikai szabályok, egyező pointer- vagy struktúratípus, stb.). A kifejezés eredménye lvalue lehet, ha mindkét ág ugyanazt az lvalue-típust adja. |
Precedencia |
Alacsonyabb, mint a logikai && és || operátoroké.
|
Oldalhatás |
Csak a kiválasztott ág fut le → a rövidre zárás (short-circuit)
miatt mellékhatásokkal is biztonságosabb, mint egy kétszer értékelt if-kifejezés. |
//egyszerű pl.
int min = (a < b) ? a : b;
//bonyolultabb pl1.
((x < 0) ? x : y) = 0; /* csak akkor érvényes, ha x és y is int változó */
//Ha x < 0 igaz, x lesz kinullázva, különben y.
//bonyolultabb pl2.
printf("%s\n", flag ? "OK" : "FAIL");
//Formázott kiírás választott szöveggel.
//bonyolultabb pl3.
#define ABS(x) ((x) < 0 ? -(x) : (x))
//Érték-visszaadó „inline” funkció.
switch (c) {
case 'a':
puts("alma");
break; /* ← itt lépünk ki a switch-ből */
case 'b':
puts("banán");
break;
}
puts("itt folytatjuk"); /* ide érkezik a vezérlés */
//"fall through"
switch (n) {
case 1:
puts("egy");
/* nincs break → lefut a 2. ág kódja is */
case 2:
puts("kettő");
break;
}
Operátor | Jelentés | Példa (32-bites unsigned) | Eredmény (hex) | Rövid magyarázat |
---|---|---|---|---|
& |
bit-AND | 0xF0 & 0xCC |
0xC0 | Csak a mindkét operandusban 1-es bitek maradnak. |
| |
bit-OR | 0x0F | 0x30 |
0x3F | 1-es, ha bármelyik operandus bitje 1. |
^ |
bit-XOR | 0xAA ^ 0xFF |
0x55 | 1-es, ha a bitek különböznek. |
~ |
bit-NOT (negáció) | ~0x0000000F |
0xFFFFFFF0 | Minden bitet megfordít. |
<< |
balra tolás | 0x01 << 4 |
0x10 | Bitenkénti szorzás 2-vel az eltolás számával. |
>> |
jobbra tolás | 0x80 >> 3 |
0x10 (logikai) | Osztás 2-vel. Előjelesnél aritmetikai vagy logikai eltolás implementáció-függő. |
uint8_t flags = 0b00000101; // bit0 = ON, bit2 = ON
flags |= 0b00001000; // 3. bit bekapcsolása (OR)
flags &= ~0b00000001; // 0. bit kikapcsolása (AND + NOT)
if ((flags & 0b00001000) != 0) {
/* a 3. bit most aktív */
}
Logikai operátorok és miért kellettek
Operátor | Jelentés | Példa | Kiértékelés | Eredmény értéke |
---|---|---|---|---|
&& |
logikai ÉS | a && b |
short-circuit: ha a hamis, b nem fut le |
0 vagy 1 |
|| |
logikai VAGY | x > 0 || y < 0 |
short-circuit: ha x > 0 igaz, y < 0 nem fut |
0 vagy 1 |
! |
logikai NEM | !ptr |
— | 0 vagy 1 |
Szempont | Leírás |
---|---|
Egész kifejezések igaz-hamis tesztelése |
A feltételes utasítások (if , while , for ) egész kifejezések igazságértékét kérik.
A && és || pontosan erre szolgál: egyetlen igaz/hamis eredményt (0 / 1) ad, nem pedig bit-mintát.
|
Rövidre zárás (short-circuit) |
if (p && *p == 'x') – ha p NULL , a jobb oldal meg sem próbál dereferálni, így elkerüljük a futási hibát.
|
Bit-AND vs. logikai AND |
A & mindkét oldalt kiértékeli, tehát p & *p önmagában nem biztonságos,
ha p lehet NULL .
|
Olvashatóság és hordozhatóság |
status & READY_MASK bit-tesztnek jó, de if (x & y) nem egyértelmű,
hogy bit-kombinációt vizsgálunk vagy csak elfelejtettük a && -et.
A logikai operátor mindig feltételnek szánt, egyértelmű formát ad.
|
Nem egész típusok támogatása |
A logikai operátor bármely skálázható típuson használható (például double , pointer, enum ),
és az eredmény mindig int (0 vagy 1).
A bitműveletek ezzel szemben csak egész típusokon definiáltak.
|
Mi az a pointer?
Definíció: A pointer (mutató) olyan változó, amely más objektum címét tárolja.
Típus-szigorú: egy int*
csak int
-re mutathat, egy char*
csak char
-ra stb.
int n = 42; /* egy normál egész */
int *p = &n; /* p az n címe */
Alapvető műveletek
Operátor | Név | Példa | Jelentés |
---|---|---|---|
&obj |
address-of | &n |
Az objektum címe |
*ptr |
dereference | *p = 50; |
A címzett tartalmára hivatkozik |
ptr + k |
pointer aritmetika | p + 1 |
A k-adik elem címe azonos típusú objektumok sorozatában |
Egyszintű indirekció
// egyszintű indirekció
int x = 7;
int *px = &x; // indirekt hozzáférés: *px
printf("%d", *px); /* 7 */
Többszintű indirekció
// többszintű indirekció
int v = 3;
int *pv = &v; // &v → int*
int **ppv = &pv; // &pv → int**
**ppv = 99; // két csillag: eljutunk v-ig
/* Dinamikus tömbök (char** argv), mátrixok, összefűzött listák fejmutatója,
vagy olyan API-k, amelyek pointert várnak kimeneti paraméterként. */
Indirekció függvénymutatóval
int add(int a, int b) { return a + b; }
int (*op)(int,int) = add;// op egy függvény címe
int sum = op(2,3); // indirekt hívás
Művelet | Mit jelent a fordító számára? | Érvényességi feltétel | Eredmény típusa |
---|---|---|---|
p + n, n + p | p cím + n × sizeof(*p) bájt | p és a végpont ugyanabban a tömbben vagy “one-past” | ugyanaz a pointer-típus |
p - n | p cím − n × sizeof(*p) bájt | mint fent | pointer-típus |
++p, p++, --p, … | p = p ± 1 elem (nem bájt!) | mint fent | pointer-típus |
p1 - p2 | elemek száma (ptrdiff_t) a két cím között | p1, p2 ugyanazon tömb elemére vagy one-past-jára mutat | ptrdiff_t |
p[i] vagy *(p+i) | *(p + i) – ekvivalens az indexeléssel | mint fent | lvalue *p típus |
//1. Példa – lineáris bejárás
int a[5] = {2,4,6,8,10};
int *p = a; // &a[0]
while (p < a + 5) { // one-past pointerig érvényes
printf("%d ", *p); // dereferencia
++p; // ugrás a következő int-re
} // (4 bájttal 32-bitesen)
//2. Példa – Különbség két pointer között
double v[100];
double *first = v + 20;
double *last = v + 80;
ptrdiff_t elems = last - first; // 60, nem 480 bájt
//3. Példa – Különbség két pointer között
double v[100];
double *first = v + 20;
double *last = v + 80;
ptrdiff_t elems = last - first; // 60, nem 480 bájt
//4. Példa – Szeletek
int *begin = arr + start;
int *end = arr + end_excl; // mutathat one-past-ra
for (int *p = begin; p < end; ++p) process(*p);
//5. Példa – Mutató + index
size_t idx = 17;
arr[idx] == *(arr + idx); // teljesen azonos kód keletkezik
Jelölés | Név | Rövid magyarázat | Tipikus művelet tömbön |
---|---|---|---|
O(1) | konstans idő | A végrehajtási idő nem függ a mérettől (n). | Indexelés – x = a[i]; az elem címe aritmetikával azonnal kiszámítható. |
O(log n) | logaritmikus | Minden lépésben megfelezi (vagy harmadolja, …) a keresési teret. | Bináris keresés előre rendezett tömbben. |
O(n) | lineáris | A teljes tömb minden elemét legalább egyszer érinti. | Lineáris keresés ismeretlen elrendezésnél; beszúrás vagy törlés középen (shift). |
O(n log n) | lineáris-logaritmikus | Hatékony rendezések elméleti alsó korlátja összehasonlítás-alapú modellben. | Merge sort, Quicksort (átlagos eset), Heapsort. |
O(n²) | kvadratikus | Minden elem minden másikkal összevetődik. | Buborékrendezés, kiválasztásos rendezés (selection sort). |
O(n³) … | polinomiális (magasabb fokú) | Tömb × tömb kombinációk többdimenziós műveleteknél. | Naiv mátrixszorzás három beágyazott ciklussal. |
Jelenség | Mi történik a gépen? | Látható tünet | Miért baj? |
---|---|---|---|
Undefined Behaviour (UB) | A C-szabvány nem írja le, mit KELL tennie a fordítónak; bármi előfordulhat. | működni látszik, segfault, fura értékek… – attól függ, épp mit lépsz le. | Lehet, hogy most „bezzeg megy”, de optimalizált fordításnál vagy más gépen elszáll. |
Stack-smashing (stack-based buffer overflow) | Lokális tömb túlírása → felülírod a visszatérési címet / canary-t. | *** stack smashing detected *** Aborted vagy csendes exploit. | Klasszikus ROP, shellcode: tetszőleges kódfuttatás. |
Heap-corruption | malloc()-pal kapott blokk határán túl írsz. | Random crash később (free()-nél, teljesen másik kódrészben). | Sérül a malloc-header, dupla-free, use-after-free – security bug, adatvesztés. |
Information leak | „Csak” olvasod a szomszéd memóriát. | Látszólag helyes, de kiírhatod más változók / kulcsok tartalmát. | Jelszó, titkos kulcs, ASLR-címek kikerülhetnek (Heartbleed). |
Data races & teardown | Több szál ugyanazon túlcsúszott területre ír. | Megmagyarázhatatlan hibák, ritka crash. | Nehéz visszakövetni, nondeterminisztikus hibák. |
E1[E2]
Az alábbi egzakt módon értelmezendő:
* ( (E1) + (E2) )
- legalább az egyik operandusnak mutató típusúnak kell lennie,
#include <stdio.h>
int main(void)
{
int tomb[5] = { 1,2,3,4,5 };
for (int i = 0; i < 5; i++) {
printf("%d\t", tomb[i]);
printf("%d\n", i[tomb]);
}
return 0;
}
1 1
2 2
3 3
4 4
5 5
visszateresi_ertek_tipusa függvény_név(típus első_paraméter, típus második_paraméter, ...)
{
/* függvénytörzs */
/* ... */
return érték; /* ha a visszatérési_típus nem void */
}
//Paraméternevek a prototípusban! (deklaráció) elhagyhatók:
double hypot(double, double); /* OK prototípus */
//a definícióban kötelezőek.
Kulcsszó | Hová írod? | Mit ér el? | Rövid tipp |
---|---|---|---|
static | static int f(void) |
A függvény csak a forrásfájlban látható (belső kötés). |
Segédfüggvények elrejtésére. |
inline |
inline int f(int x) static inline … |
A fordító a hívás helyére másolhatja a kódot, így nincs hívási költség (ha akarja). |
Kis, gyakori függvényekhez; static inline‐t válassz, ha nem kell külső szimbólum. |
const | int f(const char *p) |
A paraméter/visszatérő adat nem módosítható. Magát a függvényt nem „rögzíti”. |
Tedd oda, ahol meg akarod tiltani az írást a hívónak vagy a függvénynek. |
Fogalom | Hol jelenik meg? | Mi tárolódik? | Élettartam | Példa |
---|---|---|---|---|
Formális paraméter (formal parameter, paraméter-név) |
A függvény deklarációjában / definíciójábanvoid swap(int *a, int *b)
|
Azonosító + típus – a függvény belső változója |
A függvény hívásának idejére automatikus tárhelyen (stack frame) |
int *a, int *b a swap törzsén belül
|
Aktuális (valós) paraméter (actual parameter, argumentum) |
A hívó oldalonswap(&x, &y);
|
Bármilyen kifejezés értéke vagy címe, amelyet a fordító átad | A hívó kódrészlet saját élettartama szerint |
&x, &y a swap hívásában
|
Előny | Rövid indok |
---|---|
Kompakt |
A puszta bájtokat írjuk ki, nincs karakter-kódolási többlet (pl. 0x00–0xFF mind engedélyezett). |
Gyors I/O |
A lemezen is, a memóriában is byte-pontos másolat; nincs parse-olás, konverzió. |
Strukturált |
Tetszőleges rekord-/tömörtáblázat-elrendezés; csak a te programod tudja a „térképet”, ezért nehezebb véletlenül vagy rosszindulatúan módosítani. |
Hardver-közeli |
Firmware-, képcímtár-, hálózati csomag- vagy mentett játékállás-fájl ugyanazzal a memóriaképpel dolgozik. |
Egyszerű írási példa
#include <stdio.h>
#include <stdint.h>
struct Record { /* 12 bájt fix */
uint32_t id; float value; /*4+4*/
uint8_t flag, pad[3];/*1+3, 4 bytera igazítás miatt pad*/
};
int main(void) {
struct Record rec = { 42, 3.14f, 1 };
FILE *f = fopen("data.bin", "wb"); /* b = binary */
fwrite(&rec, sizeof rec, 1, f); fclose(f);
return 0;
}
Egyszerű olvasási példa
#include <stdio.h>
#include <stdint.h>
struct Record {...};
int main(void) {
FILE *f = fopen("data.bin", "rb");
struct Record rec;
if (fread(&rec, sizeof rec, 1, f) == 1) {
printf("id=%u value=%f flag=%u\n",
rec.id, rec.value, rec.flag);
}
fclose(f);
return 0;
}
data.bin hexadecimálisan
00000000 2A 00 00 00 C3 F5 48 40 01 00 00 00
A legtöbb processzor azt feltételezi, hogy egy 4-bájtos (uint32_t, float) mező címe 4-es többszörös (például 0x1000, 0x1004, 0x1008 stb.).
Ha a flag után nem tennénk be a 3 bájt padding-et, akkor a következő uint32_t vagy float mező nem lenne 4-re igazítva, és az ilyen „unaligned” memóriacímeken történő olvasás-írás több dolgot jelenthet:
Lassabb lesz, mert a CPU kénytelen két memóriacímről összeollózni a teljes 4 bájtodat, vagy extra mikroutasításokat futtatni.
Egyes architektúrákon hiba, sőt kivétel keletkezik unaligned hozzáférésnél (pl. néhány beágyazott CPU-n, vagy ARM-on, ha nem konfigurálod).
#include <stdio.h>
#include <time.h>
int main(void) {
clock_t start, stop; double elteltIdo;
start = clock(); // mérés kezdete
// … Itt van a mérendő kódrész
stop = clock(); // mérés vége
elteltIdo = (double)(stop - start) / CLOCKS_PER_SEC;
printf("Eltelt idő: %.6f s\n", elteltIdo);
return 0;
}
De mégis minek?
Compiler optimalizáció beállítás VS 2022-ben
VS 2022 optimalizációs opciók
Beállítás | Parancssori jelző | Mire jó? |
---|---|---|
Disabled | /Od |
Minden optimalizáció kikapcsolva → gyorsabb fordítás és könnyebb hibakeresés (debug). |
Maximum Optimization (Favor Size) | /O1 |
Kisebb bináris méret előnyben → memória- és cache-igény csökkentése. |
Maximum Optimization (Favor Speed) | /O2 |
Gyorsabb futás előnyben → inlining, loop-unrolling, konstans-propagáció stb. |
Optimizations (+Favor Speed) | /Ox |
Teljes /O2 plusz extra makró-inlining, frame-pointer eltávolítás, gyorsciklus-utak. |
Custom | — | Egyéni /Ob , /GF , /GS stb. flag-ek a Command Line fülön. |
/O1 - Size
Kis bináris méret: a fordító igyekszik minimalizálni a kód méretét, kevesebb inline-olás és loop-unrolling, egyszerűbb utasítások./O2 - Speed
Gyors futás: agresszívebb inlining, loop-unrolling, konstans-propagáció, elágazás-átalakítás stb.Inlining
A fordító a függvényhívás helyére közvetlenül beírja a hívott függvény törzsét, így elmarad a call/ret overhead, több optimalizáció jöhet létre a „lapított” kódban, de nagyobb lehet a bináris méret.Loop-unrolling
// Eredeti
for(i=0; i<100; ++i) sum += a[i];
// 4× unrolled
for(i=0; i<100; i+=4) {
sum += a[i];
sum += a[i+1];
sum += a[i+2];
sum += a[i+3];
}
Egy for- vagy while-ciklus testét többszörösen egymás után másolja a fordító, például 4-szeresével, így kevesebb a ciklusfej-ellenőrzés és ugrás Konstans-propagáció
int x = 3;
int y = x * 5 + 2; // fordításkor -> int y = 17;
Ha egy változó értéke fordítási időben ismert konstans, akkor a fordító a kifejezésekben helyettesíti azt, és kiszámolja előre:
Elágazás-átalakítás
for (…) {
if (flag) { bodyA; } else { bodyB; }
}
↓
if (flag) for (…) bodyA;
else for (…) bodyB;
Elágazás-átalakítás
// Eredeti:
if (cond) {
x = foo();
}
if (cond) {
y = bar();
}
// Optimált (branch-fusion):
if (cond) {
x = foo();
y = bar();
}
Elágazás-átalakítás
#include <stdbool.h>
int process(int v, bool flag) {
// Hint: feltételezzük, hogy flag gyakrabban igaz
if (__builtin_expect(flag, 1)) {
// gyorsabb út, előnyben
return v * 2;
} else {
return v + 1;
}
}
GCC fordító WSL-en (Windows Subsystem for Linux) belül telepíthető, VS 2022-ben MSVC van...
Elágazás-átalakítás
// Eredeti:
if (idx < N) {
result = array[idx] * 10;
}
// Optimált (speculatív hoisting + mask):
{
int tmp = array[idx] * 10; // mindig végrehajtjuk
if (idx < N)
result = tmp;
// ha idx>=N, tmp kiszámolása kidobódik
}
//civil.h
#pragma once
/* Csak előrejelzés*/
typedef struct civil civil_t;
/* Konstruktor / destruktor */
civil_t *civil_create(int igazolvanyszam, int eletkor);
void civil_destroy(civil_t *c);
/* Getterek */
int civil_get_igazolvanyszam(const civil_t *c);
int civil_get_eletkor (const civil_t *c);
double civil_get_karizma (const civil_t *c);
double civil_get_ero (const civil_t *c);
double civil_get_intelligencia(const civil_t *c);
//civil.c
#include "civil.h"
#include <stdlib.h>
struct civil {
int igazolvanyszam,
eletkor;
double karizma,
ero,
intelligencia;
};
//függvénynek pointert kell visszaadnia
civil_t *civil_create(int igazolvanyszam, int eletkor) {
civil_t *c = malloc(sizeof *c);
if (!c) return NULL;
c->igazolvanyszam = igazolvanyszam;
c->eletkor = eletkor;
c->karizma = 1.0; /* alapérték */
c->ero = 1.0;
c->intelligencia = 1.0;
return c;
}
void civil_destroy(civil_t *c) {
free(c);
}
int civil_get_igazolvanyszam(const civil_t *c) {
return c->igazolvanyszam;
}
int civil_get_eletkor(const civil_t *c) {
return c->eletkor;
}
double civil_get_karizma(const civil_t *c) {
return c->karizma;
}
double civil_get_ero(const civil_t *c) {
return c->ero;
}
double civil_get_intelligencia(const civil_t *c) {
return c->intelligencia;
}
//main.c
#include <stdio.h>
#include "civil.h"
int main(void) {
civil_t *c = civil_create(12345, 30);
if (!c) return 1;
printf("Igazolványszám: %d\n", civil_get_igazolvanyszam(c));
printf("Életkor: %d\n", civil_get_eletkor(c));
printf("Karizma: %.2f\n", civil_get_karizma(c));
printf("Erő: %.2f\n", civil_get_ero(c));
printf("Intelligencia: %.2f\n", civil_get_intelligencia(c));
civil_destroy(c);
return 0;
}