[C] Pointer naar struct array

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • 2_05
  • Registratie: November 2004
  • Laatst online: 24-06 21:19
Ik krijg het niet voor elkaar om een functie aan te roepen met een pointer naar een struct array. Dit is wat ik doe:

C:
1
2
3
4
5
6
7
8
9
10
11
12
13
int main(const int argc, const char * argv[])
{
    struct STRUCT_TYPE sP[9];
    sP[0].w=376;
    printf("w=%i\n",sP[0].w); printf("\&w=%i\n",&(screenPic[0].w));
    dd(&sP);
}

void dd(struct STRUCT_TYPE *sp[])
{
    printf("w=%i\n",sp[0]->w);
    printf("&w=%i\n",&(sp[0]->w));
}

In mijn geval geeft dit:
w=376
&w=10808796
w=19509
&w=6815752


Ik heb al allerlei manieren geprobeerd voor het doorgeven van de pointer, maar hij blijft verkeerd pointen. Waar ga ik de mist in?

Acties:
  • 0 Henk 'm!

  • user109731
  • Registratie: Maart 2004
  • Niet online
Een array in C kun je zien als een pointer naar het eerste element, en een pointer kun je indexeren. Je kunt dus gewoon de pointer meegeven aan je dd functie:
C:
1
dd(sP); 

dd krijgt vervolgens een pointer naar een struct. Die pointer kunnen we benaderen als array:
C:
1
2
3
4
void dd(struct STRUCT_TYPE *sp) 
{ 
    printf("w=%i\n",sp[0].w); 
}

Acties:
  • 0 Henk 'm!

  • EddoH
  • Registratie: Maart 2009
  • Niet online

EddoH

Backpfeifengesicht

Ter aanvulling:

Voor de leesbaarheid en veiligheid liever:
C:
1
2
3
4
void dd(struct STRUCT_TYPE *sp) 
{ 
    printf("w=%i\n",sp->w); 
}


of

C:
1
2
3
4
void dd(struct STRUCT_TYPE *sp, unsigned int arrayLength) 
{ 
    printf("w=%i\n",sp[i].w); 
}

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 19:52

.oisyn

Moderator Devschuur®

Demotivational Speaker

Compilet die code? C blijft me keer op keer verbazen. In C++ zou je een compile error gekregen hebben, waaruit ook meteen blijkt waarom je code fout is. Je krijgt dan een error als "can't convert struct STRUCT_TYPE(*)[9] to struct STRUCT_TYPE**"

In C en C++ zijn arrays en pointers in veel gevallen verwisselbaar. Een array is impliciet te converteren naar een pointer naar het eerste element, en een pointer kun je weer accessen alsof het een array is:
C:
1
2
3
4
int array[10];
array[5] = 34;
int * ptr = array;  // ptr wijst nu naar &array[0]
printf("%d", ptr[5]);  // ptr is gewoon te benaderen als array


Wat jij echter doet, is het adres opvragen van een array met de & operator. Het resultaat is dus een pointer naar de hele array, en niet naar het eerste element. Zou je die pointer benaderen als array, dan is ieder element zelf dus ook weer een array. In bovenstaand voorbeeld zou een dergelijke pointer dus wijzen naar een int[10]:
C:
1
2
3
4
int (*ptr2)[10] = &array;
printf("%d", ptr2[0][5]);
// of
printf("%d", (*ptr2)[5]);


In je dd() functie definieer je echter dat de parameter een struct STRUCT_TYPE *sp[] is. Dat is equivalent aan een struct STRUCT_TYPE **sp, met andere woorden, een pointer naar een pointer, en niet een pointer naar een array.

C:
1
int ** ptr3 = &array;  // dit mag in C, maar is fout


Nou lijkt dat wellicht hetzelfde aangezien je een pointer als array kunt benaderen, maar onder water gebeurt er heel iets anders. Een pointer is in geheugen simpelweg een geheugenadres. Bij een array staat een dergelijke verwijzing nergens opgeslagen, de array is gewoon een aaneengesloten blok van elementen. Oftewel, ptr2 verwijst naar 10 opeenvolgende ints, maar van ptr3 verwacht de compiler dat hij naar een andere pointer wijst. Daarom geeft ptr2[0][5] ook niet hetzelfde resultaat als ptr3[0][5]. Sterker nog, als je mazzel hebt crasht je programma, maar zo niet dan moet je maar hopen dat je niet willekeurig geheugen aan het aanpassen bent.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • 2_05
  • Registratie: November 2004
  • Laatst online: 24-06 21:19
Bedankt! Zo werkt het idd. Dus de pointer het eerste array element doorgeven en de array elementen niet meer beschouwen als pointers naar struct's (sp[0]->w) maar benaderen als struct's (sp[0].w).

De arraylength geef ik ook mee, maar had ik hier voor de eenvoud even weg gelaten.

Acties:
  • 0 Henk 'm!

  • G33rt
  • Registratie: Februari 2002
  • Laatst online: 22-06-2022
.oisyn schreef op woensdag 02 juni 2010 @ 10:42:
Compilet die code? C blijft me keer op keer verbazen. In C++ zou je een compile error gekregen hebben, waaruit ook meteen blijkt waarom je code fout is. Je krijgt dan een error als "can't convert struct STRUCT_TYPE(*)\[9] to struct STRUCT_TYPE**"
De code compileert wel, omdat het technisch gezien inderdaad wel mag in C - alhoewel het natuurlijk stom is dat het gewoon kan. Je krijgt in het geval van gcc (4.4.3 in mijn geval) desalniettemin wat warnings en een keurige note om je op de mogelijke fout te wijzen. Ik heb de struct even gedefinieerd dmv alleen een int w als member om het zo eenvoudig mogelijk te houden.

gbesjes@apollo /tmp $ gcc test.c
test.c: In function dd:
test.c:10: warning: format %d; expects type int, but argument 2 has type int *
test.c: In function main:
test.c:18: warning: passing argument 1 of dd from incompatible pointer type
test.c:7: note: expected struct STRUCT_TYPE ** but argument is of type struct STRUCT_TYPE (*)[9]

Regel 18 is de aanroep naar dd, regel 10 de print van &(sp[0]->w)).
Pagina: 1