C/C++ Kérdés a void pointerekről?
1. sizeof(void) -ra fordítási hibát ad. Miért?
2.
int x;
void * ptr = &x;
Itt a ptr nem jelöl ki memóriaterületet (könyv szerint). Ez mit jelent pontosan? Ha nem void pointert használok akkor a memóriaterületen létrejön egy pointer ami vhova mutat. A ptr számára nem jön létre külön pointerváltozó? De akkor ez azt jelentené hogy fordítási időben "létezik"?
3. Változót void típussal van értelme használni, vagy csak pointerek esetében?
void var;
Megköszönném ha segítenétek. Üdv
#9
1. Korrekt.
2. Korrekt.
Ha pl. azt mondjuk, hogy
__char* ptr;
__printf("%d", *ptr);
akkor a *ptr kifejezés egyetlen (sizeof(char)) bájtot fog kiolvasni a ptr által tárolt címről.
__int* ptr;
__printf("%d", *ptr);
Ez pedig a ptr-ben lévő címtől kezdve sizeof(int) darab bájtot olvas ki, és int-ként kezeli. Tehát ha pl. a ptr-ben 100-as cím volt, akkor a 100,101,102,103-as címeken lévő értékeket kezeli egyetlen int-ként.
3. "A "var" szimbólum létezik a C/C++ programban"
Ezt most nem vágom. Az általános típusú változóra gondolsz, mint ami pl. Visaul Basicben is van? Erről nem tudok C-ben. Pontosabban vannak ilyen megoldások, de nem részei az alap C/C++ szabványnak. (Ha jól tudom...)
"Vagy a fordító van annyira intelligens és fölöslegesen nem hoz létre újabb pointert hanem egyszerűen a "pointer" változó értékét írja át az adott címre?"
Igen, pontosan ezt teszi. A statikus változók címét fordításkor már tudjuk, így a fordító (pontosabban a szerkesztő/linker) simán berakja a helyére a konkrét címet.
A dimamikus változók/objektumok címére meg nem szoktunk & operátort használni, hiszen eleve tároljuk valahol (egy pointerben) a címüket. :)
"A & által visszaadott pointer típusa pedig automatikusan olyan típusú, amilyen kifejezésben használták a & kifejezést?"
Huh, ennek utána kellett néznem, mert hirtelen én sem tudtam.
"When applied to functions or l-values, the result of the expression is a pointer type (an r-value) derived from the type of the operand. For example, if the operand is of type char, the result of the expression is of type pointer to char. The address-of operator, applied to const or volatile objects, evaluates to const type * or volatile type *, where type is the type of the original object."
Szóval igen, olyan típusos pointert ad vissza, amilyen típusú változóra használtuk.
#10
Az & operátor nem hoz létre változót, nem foglal területet.
Ha pl. ezt mondjuk:
__char ch = 0; // mondjuk a 100-as címen van a ch
__printf("%d", ch);
akkor a printf-ben lévő ch hivatkozás valahogy így fog kinézni (nem vagyok nagy assembly guru, szóval csak Z80-szerű kóddal) :
__LD A,(100)
__PUSH A
vagyis a 100-as címről tölt valamelyik regiszterbe, és onnan kerül majd paraméterként a printf függvényhez.
Ha meg így van:
__printf("%d", &ch);
Akkor erre fordul:
__LD A,100
__PUSH A
vagyis simán a cím adódik át a printf-nek. :)
(Csak zárójelben jegyzem meg, hogy a "sizeof()" sem egy meghívandó függvény, hanem olyan operátor, amit a fordító lecserél a konkrét értékre. Azért praktikus, mert a platformtól függ, hogy mire cseréli, de ezt a fordító tudja, hogy épp milyen platformra/architektúrára fordít.)
Nagyon-nagyon köszönöm a segítségedet, mostmár teljesen érthető :)
Ha megengeded egy kérdésem még lehet ezzel a Z80 kóddal kapcsolatban?
LD A,(100)
Ha jól sejtem az A egy változó vagy regiszter lesz, az LD memóriaterületről betöltést jelent (LOAD), és akkor pedig a , utáni értéket tölti bele. A () pedig a benne lévő memóriacímen tárolt értéket adja vissza ugye?
Mégegyszer nagyon köszönöm a segítségedet :D Üdv
"Igen, pontosan ezt teszi. A statikus változók címét fordításkor már tudjuk, így a fordító (pontosabban a szerkesztő/linker) simán berakja a helyére a konkrét címet.
A dimamikus változók/objektumok címére meg nem szoktunk & operátort használni, hiszen eleve tároljuk valahol (egy pointerben) a címüket. :)"
Ehhez csak annyit, hogy előfordul nem stacken lévő objektumok címének elkérése, például referenciaként átadott változó:
void* f(int& x)
{
return &x;
}
Így persze sok értelme nincs a kódnak, de előfordul, hogy haszna vagyon neki.
Ahhoz meg, hogy lesz-e külön változó a & eredményéből, az a fordító döntése. Lehet, hogy igen, meg lehet hogy nem. Ez színtisztán optimalizációs kérdés, bízd rá.
Amúgy nagyon szép magyarázat volt, a kérdező meg még meg is értette, nagy gratuláció mindkettőtöknek :)
81%: Közben utánanéztem, Assembly-ben az utolsó kérdéses Z80-as kód így néz ki:
MOV A, [100]
Vagyis elvileg jól értelmeztem.
iostream: Köszönöm a kiegészítésed és a gratulációt. Itt gyk-n eddig ez a 2. dicséretem tőled :D
Üdv
"LD A,(100)
Ha jól sejtem az A egy változó vagy regiszter lesz, az LD memóriaterületről betöltést jelent (LOAD), és akkor pedig a , utáni értéket tölti bele. A () pedig a benne lévő memóriacímen tárolt értéket adja vissza ugye?"
Teljesen jól leírtad, az A a Z80 procinak az egyik regisztere, és az LD a 100-as címről tölt be egy bájtot az A-ba. Tehát az A nem a memórában van, nincs címe.
(Nem mintha túl sokan foglalkoznának manapság a Z80 processzorral, de én csak ebbe folytam bele annak idején. Arra akartam példát mutatni, hogy a lefordított kód néha nem olyan bonyolult, mint hinnénk, és nincs mindig szükség extra "változókra". :D)
Amúgy köszi az elismerést, pláne hogy iostream kicsit jobban képben van, mint én. :)
Kapcsolódó kérdések:
Minden jog fenntartva © 2024, www.gyakorikerdesek.hu
GYIK | Szabályzat | Jogi nyilatkozat | Adatvédelem | Cookie beállítások | WebMinute Kft. | Facebook | Kapcsolat: info(kukac)gyakorikerdesek.hu
Ha kifogással szeretne élni valamely tartalommal kapcsolatban, kérjük jelezze e-mailes elérhetőségünkön!