Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien

[C] pointer in struct pointer (array in stuct array*) uitlez

Pagina: 1
Acties:

  • BastiaanCM
  • Registratie: Juni 2008
  • Laatst online: 09:21
Kom er even niet uit 8)7 Maar het resulteert wel in een SIGSEGV, stoort me een beetje..

Stel men neme een struct:
code:
1
2
3
struct exampleStruct{
unsigned char *c;
}


Die word geinitialiseerd als volgt (array van 3):
code:
1
struct exampleStruct * eStruct = calloc(3, sizeof(struct exampleStruct));

Vervolgens de pointer naar een array: (*c word niet gebruikt als string!)
code:
1
eStruct[0].c = calloc(3, sizeof( unsigned char );


So far so good. Maar als ik de variabelen in *c vervolgens wil uitlezen, mayhem.. :(

Ik verwacht zelf dat de inhoud als volgt uit te lezen valt:
code:
1
eStruct[0].c[0]

Maar dat gaat dus niet goed. Nou dacht ik dat ik mijn pointers er inmiddels wel door had.. Uiteindelijk lukt het wel uit te lezen via &eStruct[0].c[0] maar of dat nou de bedoeling is ? Voor zover ik in mijn boek of op google kan terugvinden niet. Wie geeft mij een pointer :+ in the right direction ?

[ Voor 3% gewijzigd door BastiaanCM op 19-12-2013 17:00 ]


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 03:08
Wat je beschrijft klopt allemaal wel (behalve dat je in je voorbeeldcode een puntkomma na de struct-declaratie, en een haakje sluiten achter de tweede calloc call, vergeten bent), en dus hoort de expressie eStruct\[0].c\[0] gewoon naar 0 te evalueren.

Waaruit concludeer je dat er iets niet goed gaat?

  • Infant
  • Registratie: Januari 2008
  • Laatst online: 21-11 21:52

Infant

It's a floating Dino!

Ik zou dan denken dat het bij het uitlezen fout gaat. Hoe lees je het uit?

  • Daos
  • Registratie: Oktober 2004
  • Niet online
Je zegt dat je c niet als string gebruikt, maar daar lijkt het wel op. Of je roept array-functies aan oid.

&eStruct[0].c[0] is trouwens hetzelfde als eStruct[0].c Met c[0] pak je het eerste element en met & pak je daar weer het adres van. c is al dat adres. Doe maar eens:
C:
1
2
printf("%p\n", &eStruct[0].c[0]);
printf("%p\n", eStruct[0].c);


Edit:
Of misschien heb je c vernield. c kan door eerdere acties naar iets anders wijzen dan je stukje geheugen op de heap dat met calloc gereserveerd is. Met printf's zoals hierboven kan je vlak na je calloc en later kijken of er nog steeds hetzelfde adres in zit (hetzelfde geldt ook voor eStruct; das ook een pointer).

Edit2/3:
Werkend voorbeeldje:
C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include <stdio.h>
#include <stdlib.h>

struct exampleStruct
{
    unsigned char *c;
};

int main()
{
    struct exampleStruct *eStruct = calloc(3, sizeof(struct exampleStruct));

    eStruct[0].c = calloc(3, sizeof(unsigned char));
    eStruct[1].c = calloc(3, sizeof(unsigned char));
    eStruct[2].c = calloc(3, sizeof(unsigned char));

    printf("Address stored in eStruct: %p\n", eStruct);

    printf("Address stored in eStruct[0].c: %p\n", &eStruct[0].c[0]);
    printf("Address stored in eStruct[0].c: %p\n", eStruct[0].c);

    printf("Address stored in eStruct[1].c: %p\n", eStruct[1].c);
    printf("Address stored in eStruct[2].c: %p\n", eStruct[2].c);

    eStruct[0].c[0] = '1';
    eStruct[0].c[2] = '3';
    eStruct[0].c[1] = '2';
    eStruct[1].c[0] = '4';
    eStruct[2].c[2] = '9';
    eStruct[1].c[1] = '5';
    eStruct[2].c[0] = '7';
    eStruct[1].c[2] = '6';
    eStruct[2].c[1] = '8';

    printf("%c", eStruct[0].c[0]);
    printf("%c", eStruct[0].c[1]);
    printf("%c", eStruct[0].c[2]);
    printf("%c", eStruct[1].c[0]);
    printf("%c", eStruct[1].c[1]);
    printf("%c", eStruct[1].c[2]);
    printf("%c", eStruct[2].c[0]);
    printf("%c", eStruct[2].c[1]);
    printf("%c\n", eStruct[2].c[2]);

    printf("Address stored in eStruct: %p\n", eStruct);
    printf("Address stored in eStruct[0].c: %p\n", eStruct[0].c);
    printf("Address stored in eStruct[1].c: %p\n", eStruct[1].c);
    printf("Address stored in eStruct[2].c: %p\n", eStruct[2].c);

    free(eStruct[0].c);
    free(eStruct[1].c);
    free(eStruct[2].c);
    free(eStruct);

    return 0;
}


Uitvoer (adressen zijn bij elke run anders, maar je ziet goed dat de adressen in de pointer-variabelen voor en na de bewerkingen hetzelfde zijn):
Address stored in eStruct: 00c42a90
Address stored in eStruct[0].c: 00c42a70
Address stored in eStruct[0].c: 00c42a70
Address stored in eStruct[1].c: 00c42aa8
Address stored in eStruct[2].c: 00c42ab8
123456789
Address stored in eStruct: 00c42a90
Address stored in eStruct[0].c: 00c42a70
Address stored in eStruct[1].c: 00c42aa8
Address stored in eStruct[2].c: 00c42ab8

[ Voor 118% gewijzigd door Daos op 20-12-2013 11:23 . Reden: voorbeeldje mooier gemaakt ]


  • BastiaanCM
  • Registratie: Juni 2008
  • Laatst online: 09:21
Soultaker schreef op donderdag 19 december 2013 @ 22:04:
Wat je beschrijft klopt allemaal wel (behalve dat je in je voorbeeldcode een puntkomma na de struct-declaratie, en een haakje sluiten achter de tweede calloc call, vergeten bent), en dus hoort de expressie eStruct\[0].c\[0] gewoon naar 0 te evalueren.

Waaruit concludeer je dat er iets niet goed gaat?
Excuses, Slordigheid bij het her / over-typen. Het gaat dus niet goed omdat mijn programma een SIG_SEG ontvangt (Segmentation fault).

@Daos, dank u voor de uitgebreide reply. Inderdaad, dat gaat goed. Had ik de aanroep van pointers toch wel goed, dat is mooi. Echter blijft de issue bestaan, maar de oorzaak lijkt toch elders te zitten.

Ik heb de prints even toegevoegd in mijn programma. Wat valt mij op ? Dat de pointers opeens veranderen :
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
eStruct[0] adress: 138458744 
eStruct[0].c adress: 137140376 
eStruct[0].c[0] adress: 137140376 
eStruct[0].c[1] adress: 137140377 
eStruct[0].c[2] adress: 137140378 
eStruct[1] adress: 138458772 
eStruct[1].c adress: 137161656 
eStruct[1].c[0] adress: 137161656 
eStruct[1].c[1] adress: 137161657 
eStruct[1].c[2] adress: 137161658 
eStruct[2] adress: 138458800 
eStruct[2].c adress: 137141352 
eStruct[2].c[0] adress: 137141352 
eStruct[2].c[1] adress: 137141353 
eStruct[2].c[2] adress: 137141354 
eStruct[0] adress: 138458744 
eStruct[0].c adress: 0 
eStruct[0].c[0] adress: 0 
eStruct[0].c[1] adress: 1 
eStruct[0].c[2] adress: 2 
eStruct[1] adress: 138458772 
eStruct[1].c adress: 0 
eStruct[1].c[0] adress: 0 
eStruct[1].c[1] adress: 1 
eStruct[1].c[2] adress: 2 
eStruct[2] adress: 138458800 
eStruct[2].c adress: 0 
eStruct[2].c[0] adress: 0 
eStruct[2].c[1] adress: 1 
eStruct[2].c[2] adress: 2


Mijn programma zelf werkt wel met een pthread, maar de array word vanuit die thread geinitialiseerd..
Echter als ik dit probeer na te bootsen in een klein voorbeeld dan blijven de pointers wel constant.

Ik blijf eraan werken..

[ Voor 91% gewijzigd door BastiaanCM op 20-12-2013 11:37 ]


  • Daos
  • Registratie: Oktober 2004
  • Niet online
Het blijft giswerk, maar misschien heb je ergens een 'test' zoals
C:
1
2
if (eStruct[0].c = 0)
    printf("eStruct[0].c is null")


Vergelijken doe je met ==. = is een assignment. In bovenstaande stukje code vergelijk je niet, maar stop je 0 in eStruct[0].c (de expressie in de if-statement is daardoor altijd false, maar dat terzijde).

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Kun je in je IDE geen data breakpoint zetten? De tweede iteratie is de waarde van c veranderd, dus nu moet je alleen nog zien te achterhalen waardoor dat komt.

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”

Pagina: 1