» »

[C] struct in int[]

[C] struct in int[]

«
1
2

Karlos ::

Malo sem že pozabil C, pa se že cel dan matram kako bi vpisal array števil v strukturo
struct person{
    int id;
    int t[3];
    char *name;
}janez;

janez.id = 15;
janez.name = "Janez Novak";
int m[] = {1,2,3};
?? janez.t = ??
Sai Baba: "Dam vam to, kar hočete, da boste hoteli to, kar vam želim dati."

ERGY ::

Tako enostavno spet ni...

#include <stdio.h>
#include <stdlib.h>

struct person
{
    int id;
    int t[3];
    char* name;
}janez;


int main()
{
    janez.id = 15;
    int m[] = {1, 2, 3};
    janez.name = (char*)malloc(30*sizeof(char));
    memcpy(janez.name, "Janez Novak\0", 12);
    memcpy(janez.t, m, (3*sizeof(int)));

    printf("Person:\n");
    printf("id: %d\n", janez.id);
    printf("name: %s\n", janez.name);
    printf("T: ");

    unsigned i;
    for(i = 0; i < 3; ++i)
    {
        printf("%d ", janez.t[i]);
    }


    return 0;
}



p.s. ne pozabi še pomnilnika sprostit.. mislim da je free(janez.name)

Zgodovina sprememb…

  • spremenilo: ERGY ()

Tutankhamun ::

ERGY to si pa čist falu zdej.
AMD Phenom QUAD 9950 Black Edition, 8GB

napsy ::

memcpy(janez.t, m, 3*sizeof(int));


to bi moralo zadostovati, da skopiras tisto tabelo. Ostala koda pa zgleda kul.
"If you die, you die. But when you live you live. There is no time to waste."

Karlos ::

Hvala vsem, mi je ratalo dokončati kodo.
Sai Baba: "Dam vam to, kar hočete, da boste hoteli to, kar vam želim dati."

ERGY ::

Tutankhamun je izjavil:

ERGY to si pa čist falu zdej.


Ok. Lahko poveš še kaj pa kje, da bom vedu.

Senitel ::

Kompliciranje z mallocom za brezveze.

BigWhale ::

Senitel je izjavil:

Kompliciranje z mallocom za brezveze.


Ce bo imel pet milijonov oseb, pol mora malloc uporabit, ker na stack ne bo vsega spravil. ;>

Senitel ::

Saj ne grejo na stack... Če ga je volja jih lahko komot 5 milijonov v kodo nakuca. >:D

BigWhale ::

A stringi se na heapu alocirajo? No, tega nisem vedu. :>

Senitel ::

A je to še resna debata? :)
String (kot std::string) se jasno alocira na heapu.
Če ima:
janez.name = "Janez Novak";

Potem "Janez Novak" pristane nekje v virtualnem naslovnem prostoru procesa in se naloži tja skupaj s samo programsko kodo. Edina stvar, ki lahko pristane na stacku je pointer janez.name, pa še to ne nujno.

celebro ::

Pravzaprav gredo stringi v .data segment (std::string je C++, tema govori o C).

Problem pri neuporabi malloca je v tem, da takega stringa ne moreš popravljati "in place". Z mallocom je bolj univerzalno.

Zgodovina sprememb…

  • spremenil: celebro ()

technolog ::

string ne gre v .data segment. Kja gre samo začetna vrednost, ki se v konstruktorju kopira na heap.

BigWhale ::

Err, torej:

char foo[10] = "1234567890";

bo alociran na stacku, ce pa naredim:

char *foo;
foo = malloc(11);
strcpy(foo, "1234567890\0");
...

Bo pa spodnje alocirano na heapu? Al sem kaj narobe povedal?

Zato sem pa spraseval, ce string uporablja heap. V resnici ne vem kako deluje string, ga nisem nikoli prav prevec uporabljal.

celebro ::

technolog je izjavil:

string ne gre v .data segment. Kja gre samo začetna vrednost, ki se v konstruktorju kopira na heap.


Testni program:
#include<stdlib.h>
#include<stdio.h>

int main()
{
        char *str = "Test string\n";
        printf(str);
        return 0;
}


Izhod "gcc -O3 -S" na linuxu:
        .file   "test.c"
        .section        .rodata.str1.1,"aMS",@progbits,1
.LC0:
        .string "Test string"
        .text
        .p2align 4,,15
.globl main
        .type   main, @function
main:
        pushl   %ebp
        movl    %esp, %ebp
        andl    $-16, %esp
        subl    $16, %esp
        movl    $.LC0, (%esp)
        call    puts
        xorl    %eax, %eax
        leave
        ret
        .size   main, .-main
        .ident  "GCC: (Debian 4.4.5-8) 4.4.5"
        .section        .note.GNU-stack,"",@progbits


Uporablja direktno naslov stringa v .data segmentu. Again... To je C, ne C++. Tisti jezik, kjer še ni konstruktorjev, pa tudi podatkovnega tipa string ne.

technolog ::

Kr lepo std::string uporabi, pa boš videl, da gre na heap. Seveda se pa morebitna inicializacija shrani v .data, ker se itak nekam more.

celebro ::

Še tretjič... V programskem jeziku C ne obstaja std::string. To je v C++. Drug programski jezik.

@BigWhale: char foo[10] = "1234567890" bo pa na stacku, ker je foo lokalna spremenljivka, inicializacija bo pa izvršena s serijo move ukazov.

napsy ::

Lokalne spremenljivke se vedno shranijo v stack. Dinamicno alicoran prostor pa se (ponavadi) shrane v heap.

char *ime = "Janez";


je 'string literal', kar pomeni, da se ga ne sme spreminjat. Nisem pa siguren kam se to zalocira. My best guess je na stack.

(sicer C standard ne definira "stack" ali pa "heap". To je stvar implementacije)
"If you die, you die. But when you live you live. There is no time to waste."

Zgodovina sprememb…

  • spremenil: napsy ()

BigWhale ::

Ok, nevem zakaj sem omenjal string. String je iz ene druge teme. Se pardoniram.

Ja, ce imas char * potem je treba malloc() uporabiti.

napsy ::

BigWhale je izjavil:


Ja, ce imas char * potem je treba malloc() uporabiti.


ni res. Kot vidis iz primera ki sem ga napisal.
"If you die, you die. But when you live you live. There is no time to waste."

Senitel ::

char *str je samo pointer. Kaže lahko kamor koli hočeš. Lahko kaže na heap (malloc), lahko kaže direkt v data segment ("Bla bla"). Lahko pa narediš malo bolj tricky pointer ala char str[] = "Bla bla". V tem primeru bo "Bla bla" v data segmentu in se potem skopira na stack in str torej kaže na stack.

BigWhale ::

napsy je izjavil:

BigWhale je izjavil:


Ja, ce imas char * potem je treba malloc() uporabiti.


ni res. Kot vidis iz primera ki sem ga napisal.


Ja, tisti primer je eno. Ce imas tak assignment, ki je znan ob compile time-u. Ce ga pa nimas, potem ti pa prakticno ne preostane drugega, kot da z malloc telovadis naokrog oziroma s calloc, da ti se za tiste nule na koncu ni treba pretirano skrbeti. :)

Senitel ::

Spet ne nujno...
char str[512];
strcpy(str, "Bla bla");

vs.
char *str = malloc(512);
strcpy(str, "Bla bla");
free(str);

napsy ::

BigWhale:

ce imas ti:
 char str[] = "Bla bla";

potem str ne kaze nikamor ker ni kazalec. je pa zacetni polozaj na tist array, ki ga ustvaris in se nahaja na stacku.

... oziroma se popravljam. &str[0] kaze na zacetni polozaj arraya, sam objekt 'str' pa je array.
"If you die, you die. But when you live you live. There is no time to waste."

Zgodovina sprememb…

  • spremenil: napsy ()

BigWhale ::

Govoril sem o pointerjih na character. Torej, da bom povsem natancen, kadar imas pointer na character, in mu ne assignas vrednosti pred prevajanjem, moras zadevo potem urediti z m/calloc(), drugace se ti ne obeta nic dobrega.

Ce imas pa array of characters je pa stvar seveda drugacna. :) In spet je razlika med char[] in pa char[50].

technolog ::

napsy je izjavil:

BigWhale:

ce imas ti:

char str[] = "Bla bla";

potem str ne kaze nikamor ker ni kazalec. je pa zacetni polozaj na tist array, ki ga ustvaris in se nahaja na stacku.

... oziroma se popravljam. &str[0] kaze na zacetni polozaj arraya, sam objekt 'str' pa je array.


C nima objektov. str je še vedno kazalec tipa char*, le da ga na moreš spreminjat v runtimu. In fact, spodnja stavka sta identična:

char str[] = "Bla bla";
char *str = "Bla bla";

napsy ::

Technolog:
int starost = 17;


'starost' je objekt tipa int.

int *p_a;
int a[12];

Objekta 'a' in 'p_a' si nista enakovredna. 'a' je objkt tipa tabele desetih 'int' vrednosti, objekt 'p_a' je kazalec na objekt tipa int. To, da mislis da sta ta dva stavka enakovredna je tipicna zacetniska napaka.
"If you die, you die. But when you live you live. There is no time to waste."

Zgodovina sprememb…

  • spremenil: napsy ()

technolog ::

a[] je enako kot *a, ni pa enako kot naprimer a[10]. Jasno sedaj?

napsy ::

Deklaracija praznega arraya je enaka kot deklaracija arraya s podano dimenzijo. Razlika je le v tem, da pri prvi deklaracijo dimenzijo arraya ugotovi prevajalnik s pomocjo inicializacije take tabele.

Torej tvoja prejsnja izjava se vedno ne drzi.
"If you die, you die. But when you live you live. There is no time to waste."

Zgodovina sprememb…

  • spremenil: napsy ()

MrBrdo ::

technolog ima prav. napsy ti pa sploh ne veš o čem govoriš, kar dokazuje že to da misliš da je "int" objekt v C. In a[10] ni tipa tabele ampak je kazalec, cisto enako kot je a* kazalec. Razlika je samo v tem da prevajalnik sam poskrbi za alokacijo pomnilnika in priredi vrednost kazalcu, ter da je kazalec konstanta (ni ga mogoce spreminjat). Medtem ko a[] mislim da ni konstanta (ne da se mi preverjat), je pa v vecini pogledih enako a*.

Tisti ki govorite o objektih v C seveda nimate pojma, za kaj se gre.
MrBrdo

Zgodovina sprememb…

  • spremenilo: MrBrdo ()

napsy ::

MrBrdo, zmeden si. int a[10] je objekt tipa tabele za 10 int predmetov. int *a je kazalec na objekt tipa int.
Sm se spomnu da sem ze enkrat pisal o tem, mogoce komu prav pride:

http://napotnik.info/c/node2.html
"If you die, you die. But when you live you live. There is no time to waste."

technolog ::

C nima objektov, zaboga! :D

int a[10] ni nič. To je samo način, da ti prevajalniku poveš, naj rezervira 10 praznih prostorčkov velikosti sizeof(int). Ob tem se ustvari spremenjivka a, ki je v bistvu tipa int* a, ki je kazalec na prvi element tega rezerviranega prostora.

napsy ::

technolog: ne sirit krive vere ... objekt je nek prostor v pomnilniku, na katerega se ti lahko sklicujes preko imena (spremenljivka)

int a[10] ustvari tabelo za 10 int objektov ...
"If you die, you die. But when you live you live. There is no time to waste."

technolog ::

Če je pa to definicija objekta, naj me pa koklja brcne.

To drugo ti je pa celo ratal trofit, res je.

napsy ::

Taksna je vedno bila definicija objekta. Ce ne verjames, se prosim obrni na kaksno strokovno knjigo (recimo K&R).

Sicer se mi res ne da vec ponavljat 2x povedanega ... tabela != kazalec ... pozanimaj se preden se skodujes drugim ...
"If you die, you die. But when you live you live. There is no time to waste."

technolog ::

Poglej tole kodo in jo komentirej:

int a[]={1,2,3};
printf("%d", 2[a]);

Povej kaj izpiše, razen če sem se kje zmotil.

Zgodovina sprememb…

napsy ::

Spet brc v temo ... lej ti nic ne skodi ce bi sam malo pogooglu preden bi se spustil v to debato ... ne, c mi ni tuj zato prosim malo pobrskaj preden odgovoris :)
"If you die, you die. But when you live you live. There is no time to waste."

technolog ::

Kje sem se zmotil?

napsy ::

In kaj naj bil koda dokazala? Gre se samo za drugacno notacijo dereferenciranja ....

zmotil si se pri trditvi, da drzi array == pointer kar se vedno vztrajno trdim da to ne drzi
"If you die, you die. But when you live you live. There is no time to waste."

technolog ::

Lej, "tabela" je abstrakten pojem, ki ga uporabljamo ljudje, da lažje razumemo o čem se pogovarjamo. Vsaj v Cju.

V Cju tabela kot taka ne obstaja, obstaja samo kazalec, ki kaže na prvi element, s tem da ta kazalec lahko poljubno premikamo in tako dobimo kazalce do vseh elementov.

Tako da for the sake of argument, array == pointer. Tip spremenljivke je enak. V obeh primerih tip *.

Jaz se sedaj umikam, preveri si sam. Jst sm stara garda programerjev, nimam se namena kregat in te tle prepričevat.

Zgodovina sprememb…

napsy ::

Om ok ... recmo da mas prav. Potem bi sledeca koda morala delovati:

#include <stdlib.h>
#include <stdio.h>

int main() {
    char a[] = "Janez";
    char *b = "Metka";

   // torej, ce sta a in bi enaka (oba dva tipa char*),
   // potem se to mora prevesti

    a = "Novak";
    b = "Kardelj";
}


tabela ni samo pojem, gre se za drugacno predstavitev podatkov v pomnilniku ... ce si stari macek potem ga je nekdo mocno zalomil ...
"If you die, you die. But when you live you live. There is no time to waste."

Zgodovina sprememb…

  • spremenil: napsy ()

napsy ::

Ne gre se samo za koncept, zapis podatkov v pomnilniku je drugacen. Nekdo ocitno pise zelo slabe knjige oz. tutoriale.
"If you die, you die. But when you live you live. There is no time to waste."

MrBrdo ::

napsy: ti pa si smešen. Trdiš nekaj, kot utemeljitev pa daš link na nekaj kar si sam napisal. Zelo kredibilno :D

In sploh ne gre za drugačno predstavitev podatkov v pomnilniku. V obeh primerih imaš string literal (ki se po vsej verjetnosti nahaja v .data sectionu programa), in kazalec nanj. Razlika je samo v tem ali je kazalec konstanta ali ne, ter ali prevajalnik generira ukaze za kopiranje literala v sklad ( v primeru ko uporabljaš [] bo kopiral na sklad, sicer je kazalec direktno v data section)... To pa nima veze (v tem primeru) s predstavitvijo v pomnilniku ampak samo s tem, kaj počne prevajalnik. Če bi npr. v tvojem primeru uporabil inline assembler bi lahko spremenil vrednost tudi za a (predvidevam da te to "moti"). In spremenil bi KAZALEC ne pa vsebino! Saj vsebine string literalov NIKOLI ni dovoljeno, čeprav včasih to lahko narediš (v kolikor data section ni write-protected) ampak so posledice nedoločljive. V primeru ko imaš [] notacijo prevajalnik SKOPIRA literal iz data sectiona v sklad, zato tudi vsebino lahko spreminjaš. Še vedno pa gre za KAZALEC, nikakor pa ne za objekt.

Še enkrat, v C NI OBJEKTOV, so samo primitivni podatkovni tipi ter strukture, objektov pa NI.
MrBrdo

Zgodovina sprememb…

  • spremenilo: MrBrdo ()

napsy ::

prevajalniku verjames?


aaa.c:11:7: error: incompatible types when assigning to type 'char[6]' from type 'char *'


ce govorimo o c-ju, govorimo o c-ju (in ne asm). Mesas pojem 'objekt' iz objektno-orientiranih jezikov in pojem 'objekt' kot ga pozna c. C ne definira ne 'stack' in ne 'heap'. Njemu je vseeno, kaksna je implementacija ... Mmm ne da se mi vec razlagat ...
"If you die, you die. But when you live you live. There is no time to waste."

Zgodovina sprememb…

  • spremenil: napsy ()

MrBrdo ::

Pa poskusi obratno, char * priredi vrednost char[6]. Po tvoji logiki ne bi smelo it skozi, pa gre... In kaj dobiš, če castaš char[6] v (int) (char *) in izpišeš vrednost (dobiš vrednost kazalca)? In zakaj ni warningov? Razloži...
V obratnem primeru gre za napako ker je podatkovni tip bolj natančno določen, in ker ni nujno da ima char * vsebino točno 6 znakov. To nima prav nobene povezave z predstavitvijo v pomnilniku ampak le s tem da te prevajalnik hoče zaščitit pred napakami. Še vedno gre za kazalec le da pri char[6] vemo, da kazalec kaže na pomnilniški prostor velikosti 6*sizeof(char), medtem ko velikost rezerviranega prostora pri char * ni implicitna v podatkovnem tipu.

Razlagat ti ni potrebno saj nimaš prav. Za razumevanje delovanja C na tem nivoju kot se mi pogovarjamo pa je žal potrebno poznavanje arhitekture sistema, kar poznaš npr. če poznaš assembler. Boš moral še malo mleka popit, preden ti bo jasno.
C pozna primitivne podatkovne tipe in strukture. To je to. Nobenih objektov. Lahko pa najdeš kredibilen vir (to ni tisto kar si ti sam napisal) in nam dokažeš nasprotno.
MrBrdo

Zgodovina sprememb…

  • spremenilo: MrBrdo ()

napsy ::

Grr ful tezko ignoriram tako zanimivo debato :)

Obratno gre, ker je moj 'b' tipa char *. Torej:

b = a;


bo delovalo, ker je l-value tipa 'char *' ki dopusca prirejanje. Tvoj r-value je tipa 'char[]' in bo prevajalnik implicitno castal a v pointer na prvi element v array (se pravi &a[0]). Implicitno castanje dopusca standard in ni stvar implementacije.
"If you die, you die. But when you live you live. There is no time to waste."

Zgodovina sprememb…

  • spremenil: napsy ()

MrBrdo ::

Ne bo eksplicitno castal, če že kaj bi implicitno castal, česar pa v tem primeru tudi ne rabi počet, ker gre za popolnoma kompatibilna podatkovna tipa, noben cast ni potreben.

VREDNOST a je POMNILNIŠKA LOKACIJA kar pomeni da je a KAZALEC. Preveri sam:
int a[6];
printf("%d", (int) a);

Kako da izpiše pomnilniško lokacijo če pa po tvojem ne gre za kazalec? Nobene logike!
MrBrdo

napsy ::

sory za eksplicitno/implicitno .. sem se popravil ...

Ok vidim da si trdi oreh ... standarda se mi ne da brat ... drugi zadek na googlu: http://www.lysator.liu.se/c/c-faq/c-2.h...

spet pri tvoji kodi ... implicitno se array pretvori v pointer ...
"If you die, you die. But when you live you live. There is no time to waste."

MrBrdo ::

Seveda se pretvori, ker sta popolnoma ekvivalentna iz arhitekturnega stališča. Ti lahko arrayem zaradi mene rečeš objekti, ampak delovanje je popolnoma enako kot pri kazalcih. In tudi ko se stvar prevede v machine code je operiranje z kazalci, saj platforma (v tem primeru IA32) ne pozna koncepta arrayov.
Razlika med kazalcem in arrayom v Cju je samo v tem kakšne operacije ti prevajalnik nad njimi pusti izvajat. V končnem smislu pa vedno pridemo na kazalce.
MrBrdo

napsy ::

Ne, razlika je ta, kako jo standard definira. Ce ze govorimo o C-ju bi saj prosil, da iz tega stalisca vidis da sta array in pointer razlicna tipa z razlicnimi lastnosti ... kako se to pretvori v strojni jezik te naceloma (naceloma) ne zanima. In ce je prevajalnik implementacija jezika, potem imam prav.

Med c programerji je obicajno 'objekt' definiran kot sem ga zgoraj napisal.
"If you die, you die. But when you live you live. There is no time to waste."

Zgodovina sprememb…

  • spremenil: napsy ()
«
1
2


Vredno ogleda ...

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

Pomoc v C-ju

Oddelek: Programiranje
51183 (1095) rfmw
»

[C] problem s kazalci

Oddelek: Programiranje
141266 (1027) BigWhale
»

strcpy reče segmatation fault

Oddelek: Programiranje
101431 (1382) MasterMind
»

Pointer-ji v C-ju

Oddelek: Programiranje
291685 (1383) rokpok
»

kazalci in polje

Oddelek: Programiranje
51605 (1526) rasta

Več podobnih tem