www.elektronik.si
GNU C pomoč začetniku VI
Pojdi na stran 1, 2  Naslednja  :||:
www.elektronik.si -> Linux, unix razprave

Avtor: vilkoKraj: Dragomer PrispevekObjavljeno: Tor Jan 10, 2012 9:01 am    Naslov sporočila:  GNU C pomoč začetniku VI
----------------------------------------------------------------------------
Salamenski kazalci.

Nekako razumem, da so to spremenljivke, katerih vsebina je naslov neke druge spremenljivke. Ne zapopadem pa logike, kdaj moram pred ime kazalca dati zvezdico in kdaj ne.

Primer:
Koda:
int main()
   int  i,j,k, *ai;
   
   printf("%u \n",&i);
   ai = &i;
   printf ("%d \n",ai);
   *ai = &i;
   printf ("%d \n",ai);
   ai = &i;
   printf ("%d \n",*ai);


Dobim

Citiram:
beagleboard-svetosavska:~$ ./a.e
3196853408
-1098113888
-1098113888
-1098113888


Jasno, samo prvi izpis je pravilen.
Ali mi lahko kdo razloži, kdaj moram pred ime kazalca ai dati zvezdico in kdaj ne?
Rad bi izpisal naslov spremenljivke i, tako kot v prvem izpisu, a kot vsebino kazalca.

Hvala

Dodatno vprašanje

Koda:
 pData = (int*) calloc (i,sizeof(int));

Kaj pomeni (int*) v zgornjem ukazu?

Avtor: gumby PrispevekObjavljeno: Tor Jan 10, 2012 9:43 am    Naslov sporočila:  
----------------------------------------------------------------------------
Pri deklaraciji daš zvezdico tam, kjer hočeš imet kazalec in ne "navadno" spremenljivko (v tvojem primeru je to *ai).
V programu potem ai kaže na int, *ai je pa dereferenca tega kazalca, oz. sam int, na katerega kaže ai.
Seveda mora ai kazat na nekaj, kar obstaja. Napišeš lahko "ai=&i", v tem primeru bo ai kazal na i, *ai bo pa vrednost v i.
Upam, da ti je sedaj jasno, zakaj je samo zadnji printf() pravilen, in ne prvi Wink

Avtor: gumby PrispevekObjavljeno: Tor Jan 10, 2012 9:44 am    Naslov sporočila:  
----------------------------------------------------------------------------
(int*) je cast operator. Rezultat funkcije calloc() spremeni v kazalec na int.

Avtor: vilkoKraj: Dragomer PrispevekObjavljeno: Tor Jan 10, 2012 10:04 am    Naslov sporočila:  
----------------------------------------------------------------------------
Hvala Gumby,

V prvem primeru bi rad izpisal naslov in ne spremenljivke, in samo z prvim printf stavkom sem to dosegel, rad bi pa isto vsebino dobil tako, da izpišem vsebino kazalca, to mi nikakor ni uspelo.

Kaj je cast operator moram pa še naštudirat, v skriptih FE tega ni noter.

Pozdrav

Avtor: S53DZKraj: Ljubljana PrispevekObjavljeno: Tor Jan 10, 2012 10:19 am    Naslov sporočila:  
----------------------------------------------------------------------------
Hja tisti naslov int spremenljivke, ki ga želiš, je unsigned integer, kot imaš v formatu prvega printf.

Avtor: vilkoKraj: Dragomer PrispevekObjavljeno: Tor Jan 10, 2012 10:29 am    Naslov sporočila:  
----------------------------------------------------------------------------
Hvala, popravil sem format v Printf stavku, sedaj dobil pravo vsebino.

Avtor: ljudskoKraj: Koroška-Mežica PrispevekObjavljeno: Tor Jan 10, 2012 1:28 pm    Naslov sporočila:  
----------------------------------------------------------------------------
vilko, če pred spremenljivko napišemo v oklepajih nek tip (v tvojem primeru kazalec, ki kaže na celoštevilčno spremenljivko), nam ta stavek spremenljivko, ki sledi zaklepaju spremeni v tip, ki je napisan v oklepajih. Eh? kako mi je pa zdaj to uspelo zakomplicirati.
Primer:
imamo int st;
želimo izpisati ascii kodo številke, ki je v spremenljivki st. Seveda moramo tip spremeniti iz int v char. Naredimo takole: printf("%c",(char)st);
Upam, da je sem pomagal.

Avtor: vilkoKraj: Dragomer PrispevekObjavljeno: Tor Jan 10, 2012 1:31 pm    Naslov sporočila:  
----------------------------------------------------------------------------
Hvala LJudsko, sem nekaj takega prebal, seveda moram sprobat, sicer ne morem reč, da sem prebavil...

Avtor: ljudskoKraj: Koroška-Mežica PrispevekObjavljeno: Tor Jan 10, 2012 1:33 pm    Naslov sporočila:  
----------------------------------------------------------------------------
gumby je napisal/a:
Pri deklaraciji daš zvezdico tam, kjer hočeš imet kazalec in ne "navadno" spremenljivko (v tvojem primeru je to *ai).
V programu potem ai kaže na int, *ai je pa dereferenca tega kazalca, oz. sam int, na katerega kaže ai.
Seveda mora ai kazat na nekaj, kar obstaja. Napišeš lahko "ai=&i", v tem primeru bo ai kazal na i, *ai bo pa vrednost v i.
Upam, da ti je sedaj jasno, zakaj je samo zadnji printf() pravilen, in ne prvi Wink

vilko je napisal, da bi rad s pomočjo kazalca izpisal naslov spremenljivke, na katero kazalec kaže in ne vrednosti, ki je v njej. V zadnjem printf stavku pa počne ravno to-dereferencira kazalec in s tem dostopa do vrednosti spremenljivke, na katero kazalec kaže. Pravi printf stavek je torej drugi.
PS.: vilko, poizkusi spremenljivko i inicializirati (int i=nekaj). In potem shrani naslov v ai in ga izpiši s pomočjo ai. Ugibam.


Nazadnje urejal/a ljudsko Tor Jan 10, 2012 1:35 pm; skupaj popravljeno 1 krat

Avtor: gumby PrispevekObjavljeno: Tor Jan 10, 2012 1:35 pm    Naslov sporočila:  
----------------------------------------------------------------------------
Ja, sem spregledal...

Avtor: vilkoKraj: Dragomer PrispevekObjavljeno: Tor Jan 10, 2012 1:38 pm    Naslov sporočila:  
----------------------------------------------------------------------------
ljudsko je napisal/a:
gumby je napisal/a:
Pri deklaraciji daš zvezdico tam, kjer hočeš imet kazalec in ne "navadno" spremenljivko (v tvojem primeru je to *ai).
V programu potem ai kaže na int, *ai je pa dereferenca tega kazalca, oz. sam int, na katerega kaže ai.
Seveda mora ai kazat na nekaj, kar obstaja. Napišeš lahko "ai=&i", v tem primeru bo ai kazal na i, *ai bo pa vrednost v i.
Upam, da ti je sedaj jasno, zakaj je samo zadnji printf() pravilen, in ne prvi Wink

vilko je napisal, da bi rad s pomočjo kazalca izpisal naslov spremenljivke, na katero kazalec kaže in ne vrednosti, ki je v njej. V zadnjem printf stavku pa počne ravno to-dereferencira kazalec in s tem dostopa do vrednosti spremenljivke, na katero kazalec kaže. Pravi printf stavek je torej drugi.
PS.: vilko, poizkusi spremenljivko i inicializirati (int i=nekaj). In potem shrani naslov v ai in ga izpiši s pomočjo ai. Ugibam.


Sem že skužil..
Zmedlo me je to, da če je spremenljivka string, se pravi niz, se pravi array znakov, pa se takrat, tče hočem izpisati string (%s ) ne smem dati * pred imenom pointerja ki kaže na niz, pri ostalih tipih pa ja.

Avtor: sundancerKraj: Ljubljana PrispevekObjavljeno: Tor Jan 10, 2012 4:42 pm    Naslov sporočila: icon_great 
----------------------------------------------------------------------------
Vilko vse pohvale, ker vidim kako mocno si ugriznil v C. Bravo! Applause
Marsikomu si lahko za zgled!

Avtor: gregoralKraj: Ljubljana PrispevekObjavljeno: Tor Jan 10, 2012 6:25 pm    Naslov sporočila:  
----------------------------------------------------------------------------
Le tako naprej Vilko,
kot si že ugotovil je string oz char[] nekaj posebnega.

Namreč v C se večinoma dela z stringi ki imajo na koncu znak 0 (NULL).
Ker je to povrh vsega dovolj pogost tip podatka imaš zato v printf na voljo poseben format ki namesto vrednosti vzame naslov.

printf nato izpisuje znake dokler ne pride do znaka 0.
To je lahko tudi velik problem, ker moraš vedno poskrbeti da string zaključiš z 0.
Paziti pa moraš tudi da v spremenljivko ne vpišeš preveč znakov.

Primer:
char str[1];

// 1 pretvorimo v tekst in zapišemo v str
sprintf(str, "%d", 1);

// znak (char) '1' zapišemo v str
str[0] = '1';

// string str izpišemo na konzolo
printf("%s", str);


tole recimo že ni v redu, zdaj pa ti povej kaj je narobe?


LP, Gregor

Avtor: vilkoKraj: Dragomer PrispevekObjavljeno: Tor Jan 10, 2012 8:25 pm    Naslov sporočila:  
----------------------------------------------------------------------------
Hvala vsem za pomoč in vzpodbudo. Se bom še obračal na vas, če dovolite.
So me pa v C vrgle okoliščine, na katere ne morem vplivati: Programirati moram komunikacijo med atmeli, ki me veselo ubogajo v bascomu z Beagleboardom, na katerem teče linux in ki ga bascom ne pozna.

Po pravici povedatno, nisem navdušen nad C-jem, a kot je rekel moj kapetan v JLA davnega leta 1964: "Što se mora, nije težko!"
Hm, pa je težko. C ima ogromno pasti, sintaktičnih posebnosti, da se zgubiš v njih.

Kaj recimo pomeni v C-u dvojno dvopičje :: ?

Ja, z stringi sem delal že v bascomu, tako da mi je jasno, da je potrebno imeti dovolj prostora, ko sestavljaš string, da ne pobrišeš drugih spremenljivk. To si imel v mislih, kaj ne Gregoral?

Pričakujte v kratkem vprašanje na temo malloc in calloc.
Pa še nekaj me še žuli, a nisem še v stanju postaviti vprašanje:

Delal bom v arrayem struktur. To samo po sebi ni kritično, pač daš ime variable-strukture z indeksom pika in ime variable v strukturi.
Kaj pa če se vse skupaj nahaja v posebnem bloku memorije, kjer moram to nasloviti z pointerjem? Ali moram, da pridem do informacije najprej izračunati pointer na konkretno strukturo iz začetnega pointerja memorijskega bloka in indeksa? in še le potem prebrati podatke iz variable v indeksu? Upam, da je kaka prijaznejša pot.

Bom vprašanje postavil še enkrat kasneje z kodo, ki bo vprašanje lepše orisala.

Ppzdrav

Avtor: vilkoKraj: Dragomer PrispevekObjavljeno: Tor Jan 10, 2012 11:35 pm    Naslov sporočila:  
----------------------------------------------------------------------------
Pa nadaljujmo šolo, kjer sem učenec in vi učitelji!

Vzemimo da potrebujem strukturo:
Koda:
struct list
  {   int koda;
   char tekst[16];
  } vnos, *listp, *listp1 ;

in sicer 20 komadov le te. A je ne definiram kar tukaj, temveč zahtevam zato poseben memory blok.
Le tega lahko zahtevam ali z
Koda:
   listp = (struct list *)calloc(20, sizeof(struct list ) );

ali z
Koda:
   listp = (struct list *)malloc(sizeof(struct list ) * 20);

Oba ukaza mi napolnita pointer *listp z naslovom memory bloka.

Prvo vprašanje: ali sta oba ukaza enakovredna, dobim z obema isto?


In sedaj želimo ta memory blok napolniti z podatki.
Recimo da želimo v strukturo z indeksom i v polje Koda napisati vrednost 10:

Prenesem pointer listp v listp1. Ker bom z njim računal, ne smem izgubiti originalne vrednosti.
Koda:
listp1 = listp;

Potem izračunam pointer za i-to strukturo v memory bloku:
Koda:
listp1 = listp1 + i;

(Pri računanju s pointerjem se aditiv pomnoži z dolžino variable, za katero velja pointer, v tem slučau z dolžino strukture.)
In sedaj v polje koda prenesem vrednost:
Koda:
listp1->koda = 10;


Zapleteno, kaj? A verjetno je preprostejša pot, ki je ne poznam.
Če jo poznate, prosim za poduk. Prosim tudi za popravke, če sem kje zabrljal kaj.
Hvala!

Bo morda kdo rekel, zakaj kompliciram!
Moja rešitev predvideva uporabo Shared Memory Block-a, ki je nekaj podobnega, ravno tako ga za zahtevam od Linuxa in dobim pointer. In v njem imam namen naphati podatke, ki pa bodo na volju tudi drugim (no drugemu) programu v sistemu Linux. Zato moram to tehniko obvladati.
(Tisti drugi program bo, upam, pisal nekdo drug.)

Stran 1 od 2

Powered by phpBB © 2001,2002 phpBB Group