» »

[C/C++] Prehod iz jave

[C/C++] Prehod iz jave

marjan_h ::

Prešel sem iz jave na C in C++ in imam nekaj vprašanj kar zadeva dinamično zaseganje pomnilnika in kazalce.

1. V knjigi sem prebral da ima C jezik podatkovni tip "strojna beseda" vendar nisem videl nobenega primera, zato ne vem čemu je namenjen in kako se ga uporablja?

2. Zanima ali ni dovoljeno v C jeziku če imamo strukturo (struct) Knjiga da ne priredimo takole:
Knjiga.naslov = "Biblija";

ampak moramo tako:
strcpy(Knjiga.naslov, "Biblija");


3. Videl sem v dokumentaciji primer za odpiranje datoteke:
FILE *fopen( const char * filename, const char * mode );

Vendar kako naj vem da mu moram dati za filename string? Ko sem videl kazalec, bi menil da mu moram dati
char c = 'a';
char b = 'r';
fopen(&c,&b);


4. Ni mi jasno dinamično zaseganje pomnilnika, saj lahko od uporabnika/datoteke izveš koliko veliko tabelo potrebuješ.
Recimo:
    int v;

    cout << "Velikost tabele?" << endl;
    cin >> v;
    int tabela[v];

    cout << "Tabela je velika: " << sizeof(tabela) << endl;




Hvala za vašo pomoč.

metalc ::

1. Sam C kot standard niti ne pozna tipa "beseda" (word), temveč char, short, int, long (imajo lahko spredaj še unsigned). Da bo stvar še pestrejša, z izjemo char niti ne specificira njihove dolžine. Nekateri prevajalniki (npr, MSVS) resda poznajo tip word, ki je nekje določen z makrom #define. Kako točno je definiran, poiščeš v dokumentaciji za izbran prevajalnik oz. kar poiščeš njegovo definicijo.

2. Kako je sploh definiran 'naslov'? Če je kot C niz (char* ali char[10]), potem moraš za drugi primer (strcpy) poskrbeti, da ima alociranega dovolj pomnilnika za tvoj niz plus še en zlog za terminator ('\0').

3. char* je dokaj tricky zadeva in lahko pomeni ali kazalec na posamezen znak ali kazalec na niz, t.j. zaporedno polje znakov. V tem primeru moraš preučiti dokumentacijo za fopen, kjer izveš, da ukaz pričakuje drugo možnost in za ime uporabi vse znake med lokacijo, kamor kaže filename, in prvim terminatorjem '\0'.

4. Velikost tabele, kot jo hočeš podati v 5. vrstici, MORA biti znana že v fazi prevajanja (tako kot v Javi) in primer se bo prevedel le, če je 'v' določen z #define. Kadar tega ne veš vnaprej, se pač poslužiš dinamičnega alociranja, npr. s C-jevskim malloc ali C++-jevskim new. V C++ se lahko, če le smeš, poslužiš tudi containerja std::vector.

EWER115 ::

Govorim za C:

1. Neb vedu

2. Lahko, če imaš v structu naslov deklariran kot char *naslov;, drugače ne.

3. Za delo z datotekam deklariraš najprej kazalec na datoteko:

FILE *file;
potem odpreš datoteko npr. za branje, preveriš če je odpiranje uspešno (ni nujno, je pa by the book)

if((file = fopen("dat.txt","r")) == NULL){
printf("Napaka");
return 1;
}
sedaj lahko bereš iz datoteke (za pisanje pri odpiranju uporabi w )
za branje imaš spet svoje funkcije, npr. fscanf za branje ali fprintf za pisanje

4. dinamična alokacija je uporabna ko moraš med izvajanjem programa alocirati pomnilnik in takih situacij je mnogo ko vnaprej ne moreš predvideti koliko pomnilnika rabiš in si ga pač sproti alociraš, tukaj pridejo v poštev funkciji malloc in realloc več si preberi na spletu, ker se mi ne da razlagat.

Za C priporočam: C how to program, deitel

Lp!

Zgodovina sprememb…

  • spremenil: EWER115 ()

Spura ::

metalc je izjavil:


3. char* je dokaj tricky zadeva in lahko pomeni ali kazalec na posamezen znak ali kazalec na niz, t.j. zaporedno polje znakov. V tem primeru moraš preučiti dokumentacijo za fopen, kjer izveš, da ukaz pričakuje drugo možnost in za ime uporabi vse znake med lokacijo, kamor kaže filename, in prvim terminatorjem '\0'.

Tehnicno gledano char* vedno pomeni kazalec na znak. Nekatere funkcije poskusajo prebrati tudi znake, ki sledijo prvemu, do prvega znaka 0. V praksi je skoraj vedno tako kadar je argument char*, saj ce funkcija rabi samo en znak je ponavadi tip argumenta kar char.

marjan_h ::

metalc je izjavil:


4. Velikost tabele, kot jo hočeš podati v 5. vrstici, MORA biti znana že v fazi prevajanja (tako kot v Javi) in primer se bo prevedel le, če je 'v' določen z #define. Kadar tega ne veš vnaprej, se pač poslužiš dinamičnega alociranja, npr. s C-jevskim malloc ali C++-jevskim new. V C++ se lahko, če le smeš, poslužiš tudi containerja std::vector.


Meni normalno prevede program (CodeBlocks), čeprav ni znano koliko velika tabela mora biti. Določiš jo ko poženeš .exe. Saj to je dinamično kajne?

darkkk ::

@ točka4:

@4

lahko od uporabnika zveš, koliko pomnilnika hoče (to se ti zgodi @runtime)
Ko veš koliko ga rabiš, ga alociraš. Btw, kar maš v tč. 4 je c++ :)

int tabsize = 10; //tole ti pise uporabnik

int *tab = malloc(tabsize * sizeof(int));


Ko ga ne rabiš več, ga sprostiš.

win64 ::

Ko ga ne rabiš več, ga sprostiš.

free(tab)


nikakor pa tega ne delaj nad tako inicializirano tabelo(mimogrede smrdi do neba taka koda):
int tabela[v];

marjan_h ::

Ja, razumem kako ga alociraš. Vendar meni normalno prevede tisto kodo in deluje. Zakaj potem new in malloc?

smoke ::

DirectX11, takšno polje kot si ga omenil v točki 4 se v jeziku C in C++ nahaja na skladu. Ker pa je sklad omejen, je zaželjeno, da ko rabiš večjo količino spomina, le to, dobiš iz free stora (malloc / new), ali še bolje, če programiraš v C++, uporabiš razred std::vector.

Pa še en prijateljski nasvet: Ne programirat po Cjevsko v C++. Čeprav mogoče zgleda da sta jezika enaka, nista. Za nize v C++ uporabljaj za to namenjen razred, std::string, za dinamična polja (kot sem omenil že zgoraj) uporabljaj std::vector, za statična polja imaš std::array, itd.

Lep pozdrav

mallard ::

int tabela[v];

je VLA (variable length array). Legalno v C-ju (od standarda C99 naprej), nelegalno v C++. CodeBlocks po defaultu uporablja GCC prevajalnik, ki VLA dovoli kot nestandardno razširitev jezika. Uporabi -Wvla ali -pedantic opcijo, pa ti bo izpljunu opozorilo.

cen1 ::

Takole bi rekel.. najprej si razčisti pojme, ali se boš učil C ali C++. Tole kar zgoraj sprašuješ je čisti C in glede na to da prehajaš z JAVE ti raje priporočam da greš direktno na C++ in življenje bo takoj lažje. Npr, uporaba string in std namespaca ti že iz starta zelo olajša delo s stringi.
1. Bwo

2. V C++ ne bi uporabil structa ampak kar class. Struct se uporablja samo za čisto navadne podatkovne strukture, vse kar je več od tega raje ne.
Torej nekaj takega:
class Knjiga {
    public:
    string naslov;
};
Knjiga knjiga;
knjiga.naslov="Naslov";


Sicer pa ja, če hočeš v Cju moraš uporabit strcpy ker C nima pojma kaj je string.

3.
C:
FILE *fopen( "imedatoteke", "r" );

Oziroma če rabiš spremenljivke:
char a[]="imedatoteke";
char b[]="r";
FILE * pFile;
pFile = fopen( a, b );


C++: uporabiš razred fstream: http://www.cplusplus.com/doc/tutorial/f... in življenje je lažje


4. Velikost tabel mora biti znana že pred začetkom izvajanja programa da lahko zaseže potreben pomnilnik. Torej, ali uporabljaš malloc ali pa zasežeš MAX količino pomnilnika kolikor misliš da jo boš potreboval. Ni prostorsko učinkovito ampak če ni nek hud program ni noben problem..

Če uporabljaš C++ se ti s tem seveda ni treba ubadat ker lahko za dinamične strukture uporabljaš bolj napredne zadeve kot je vektor ipd. Ti ga samo inicializiraš potem pa push/pop na vektor in zadeva sama poskrbi za realokacije pomnilnika.





Torej.. glede na to da prihajaš z jave ti predlagam da se greš direktno učit C++ in se sploh ne matraš z Cjem.

Zgodovina sprememb…

  • spremenilo: cen1 ()

marjan_h ::

Aja, kako pa je lahko kar legalno od C99 standarda naprej? Ali se že od samega začetka 1970 nalaga na sklad, kar ni dinamično?

Recimo v javi ko sem dobil opozorilo stack overlow pri rekurziji sem pač povečal sklad. Ali tega ne morem v C/C++? Kako vem za koliko B moram uporabiti dinamično alokacijo?

fiction ::

BTW: Kolikor vem že od nekdaj obstaja alloca(). S tem lahko alociraš manjšo količino pomnilnika na skladu. Ko se funkcija neha izvajati, se tisto avtomatsko sprosti, saj je pomnilnik del "stack frama" funkcije, ki se odstrani s sklada. Pri malloc(), ki alocira heap, moraš reči free(), ko tistega ne rabiš več.

Sicer je to baje slaba praksa. Verjetno je že tako preveč stack overflowov...

fiction ::

marjan_h je izjavil:

Recimo v javi ko sem dobil opozorilo stack overlow pri rekurziji sem pač povečal sklad. Ali tega ne morem v C/C++? Kako vem za koliko B moram uporabiti dinamično alokacijo?
V javi je navidezni stroj in ti si zvišal njegove omejitve. Ni nujno, da je java sklad res na sistemskem skladu. "Navaden" C/C++ program teče direktno kot svoj proces pri katerem OS skrbi za regije v pomnilniku (med katere sodi tudi stack).

Omejitve lahko dobiš s pomočjo getrlimit() ter spremeniš s setrlimit() oz. v bashu z "ulimit -s". Lahko pa za proces, ki se že izvaja pogledaš /proc/<pid>/maps. Mislim, da je default omejitev 8 MB, na Windows OS pa 1 MB. V kernel spacu si pa še bolj omejen in je na voljo 1 - 2 strani (4 - 8 KB). Pa to ne pomeni, da vse lahko pokuriš...

Težko je reči neko številko, ampak recimo če je več kot 100 bajtov, uporabi kopico (dinamično je oboje). Še posebej pa če nekdo drug, ki ni direktno poklican iz tvoje funkcije tisto potrebuje.

V vsakem primeru pa ne slepo verjeti uporabniku in alocirati toliko, kolikor ti reče. Pa pri malloc() je priporočljivo vedno preveriti, če je uspel (ni nujno da je zmanjkalo pomnilnika, lahko se samo nekdo igra s setrlimit(), npr. da bi exploital ranljiv suid program).

marjan_h ::

Ok, najlepša hvala sedaj razumem.

Zanima me še ko deklariraš tabelo, so v njej shranjena naključna števila. Kaj če je tabela delno polna, in želim prepisati števila v std::vector? (v javi se vedno tabela napolni z 0.)

cen1 ::

http://stackoverflow.com/questions/8777...

Glede začetnih vrednosti tabele pa nisem siguren. Pogooglaj.

Vesoljc ::

marjan_h je izjavil:

Zanima me še ko deklariraš tabelo, so v njej shranjena naključna števila. Kaj če je tabela delno polna, in želim prepisati števila v std::vector? (v javi se vedno tabela napolni z 0.)


ko ti deklariras tabelo je njena vsebina nedefinirana. ce laufas debug, vcasih debugger sam popuca cel memory, v release-u pa ne. pac popucaj sam pa je. sej java isto naredi...

const int cBufferSize = 1024;
char buffer[cBufferSize];
memset( buffer, 0, cBufferSize );
Abnormal behavior of abnormal brain makes me normal...

Datadog ::

Vesoljc je izjavil:

marjan_h je izjavil:

Zanima me še ko deklariraš tabelo, so v njej shranjena naključna števila. Kaj če je tabela delno polna, in želim prepisati števila v std::vector? (v javi se vedno tabela napolni z 0.)


ko ti deklariras tabelo je njena vsebina nedefinirana. ce laufas debug, vcasih debugger sam popuca cel memory, v release-u pa ne. pac popucaj sam pa je. sej java isto naredi...


const int cBufferSize = 1024;
char buffer[cBufferSize];
memset( buffer, 0, cBufferSize );


Statični in globalni so zeroed out. Lokalnega scope-a pa so kot si rekel undefined... I think.

Vesoljc ::

Datadog je izjavil:

Vesoljc je izjavil:

marjan_h je izjavil:

Zanima me še ko deklariraš tabelo, so v njej shranjena naključna števila. Kaj če je tabela delno polna, in želim prepisati števila v std::vector? (v javi se vedno tabela napolni z 0.)


ko ti deklariras tabelo je njena vsebina nedefinirana. ce laufas debug, vcasih debugger sam popuca cel memory, v release-u pa ne. pac popucaj sam pa je. sej java isto naredi...


const int cBufferSize = 1024;
char buffer[cBufferSize];
memset( buffer, 0, cBufferSize );


Statični in globalni so zeroed out. Lokalnega scope-a pa so kot si rekel undefined... I think.


"assume nothing question everything" :)
Abnormal behavior of abnormal brain makes me normal...

Datadog ::

Vesoljc je izjavil:



"assume nothing question everything" :)


Ok ok bi moral napisat če se prav spomnim. In zgleda se :)

When declaring a regular array of local scope (within a function, for example), if we do not specify otherwise, its elements will not be initialized to any value by default, so their content will be undetermined until we store some value in them. The elements of global and static arrays, on the other hand, are automatically initialized with their default values, which for all fundamental types this means they are filled with zeros.

fiction ::

Datadog je izjavil:

Statični in globalni so zeroed out. Lokalnega scope-a pa so kot si rekel undefined... I think.
Imaš prav. Sej tudi lokalne spremenljivke so v bistvu "nedefinirane" samo po standardu. Teoretično bi lahko predvidel, kakšne bodo glede na to, kaj je prej pisalo v tistem delu pomnilnika. Ampak kako že pravijo: assumption is the mother of all f...ups.


Vredno ogleda ...

TemaSporočilaOglediZadnje sporočilo
TemaSporočilaOglediZadnje sporočilo
»

[C++] vprašanja (strani: 1 2 3 4 5 6 7 8 9 )

Oddelek: Programiranje
44727236 (11782) aljazko1995
»

[C] struct in int[] (strani: 1 2 )

Oddelek: Programiranje
657277 (6350) MrBrdo
»

[C++] prevajalnik hoce konstruktor za strukturo

Oddelek: Programiranje
182585 (2289) Tr0n
»

int to string v c++

Oddelek: Programiranje
272320 (2048) OwcA
»

c++ datoteke

Oddelek: Programiranje
464026 (3515) Vesoljc

Več podobnih tem