Toon posts:

[C] Declareren van matrix van floats

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Ik wil geheugen reserveren voor een dynamische twee dimensionale matrix van floats.
Dit wilt niet compileren :-( Help?

code:
1
2
3
4
5
6
7
8
9
10
11
//create a dynamic two dimensional matrix of floats
int create_matrix(int * dim2, const int sizeDim1, const int sizeDim2) {
  int a;
  //declare array of pointers to floats
  dim2= (int *)malloc(sizeof(int)*sizeDim2);
  //declare the memory for the floats
  for (a=0; a< sizeDim2; a++) {
    dim2[a]= (float *)malloc(sizeof(float)*sizeDim1);
  }
  return 0;
}


/home/amir/program/Cprogramin/pointer/dereferencingpointers/src/dereferencingpointers.cpp: In function ‘int create_matrix(int*, int, int)’:
/home/amir/program/Cprogramin/pointer/dereferencingpointers/src/dereferencingpointers.cpp:18: error: invalid conversion from ‘float*’ to ‘int’
gmake: *** [dereferencingpointers.o] Error 1

[ Voor 8% gewijzigd door Verwijderd op 04-12-2008 18:28 ]


Acties:
  • 0 Henk 'm!

Verwijderd

Erg summier, ik geef je weinig kans dat deze lang open blijft.
Maar nu het nog zo is: /home/amir/program/Cprogramin/pointer/dereferencingpointers/src/dereferencingpointers.cpp:18: error: invalid conversion from ‘float*’ to ‘int’

Acties:
  • 0 Henk 'm!

Verwijderd

Kun je aub de code in je TS een beetje indenteren en gebruik maken van de CODE-tag? Dat maakt het al wat overzichtelijker..

Acties:
  • 0 Henk 'm!

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

int** dim2; twee sterretjes

float** zelfs, voor floats

[ Voor 35% gewijzigd door Zoijar op 04-12-2008 18:31 ]


Acties:
  • 0 Henk 'm!

Verwijderd

Idd, je matrix met pointers naar float-pointers moet een int** worden

int ** dim2 => eerste sterretje voor een dynamisch gealloceerde array, tweede sterretje geeft aan dat de elementen in je array ook naar dynamisch gealloceerde content "wijzen"..

float* zou wel moeten werken..


I'm shutting up now...

[ Voor 5% gewijzigd door Verwijderd op 04-12-2008 18:39 ]


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Zoijar schreef op donderdag 04 december 2008 @ 18:30:
int** dim2; twee sterretjes

float** zelfs, voor floats
code:
1
2
3
4
5
6
7
8
9
10
11
//create a dynamic two dimensional matrix of floats
int create_matrix(float ** dim2, const int sizeDim1, const int sizeDim2) {
  int a;
  //declare array of pointers to floats
  *dim2= (float *)malloc(sizeof(float)*sizeDim2);
  //declare the memory for the floats
  for (a=0; a< sizeDim2; a++) {
    dim2[a]= (float *)malloc(sizeof(float)*sizeDim1);
  }
  return 0;
}

Thanks, logisch eigenlijk, het compileert nu, zometeen kijken of het werkt :-)

Acties:
  • 0 Henk 'm!

  • blackangel
  • Registratie: April 2002
  • Laatst online: 22:25
Het compileert wel, maar het is nog steeds niet goed!

Jij geeft geen adres mee. * lezen wat onhandig bij een uitleg, dus ik maak er even [] van. Je weet hoop ik, arr[0] == *arr.

Jij wilt een 2 dimensionale array maken. Dan heb je dus zoiets als arr[][]. Nu wil je deze ook nog alloceren. Daarvoor moet je het adres van arr[][] meegeven, dus float *** arr. Wat je nu doet is by val meegeven, dus uiteindelijk in functie werkt het wel correct, maar aangezien je het resultaat van je eerste malloc niet terug geeft gaat het fout. Basicly, na de functie heb je gewoon een memory leak, omdat je er geen free() meer op los kunt laten.

Wat je dan ook eigenlijk zou moeten doen, is iets als:
C:
1
2
3
4
5
6
void func(float *** arr, int par1, int par2) {
  int a;
  *arr = (float **)malloc(sizeof(float *)*par1);
  for(a=0;a<par1;a++)
    (*arr)[a] = (float *)malloc(sizeof(float)*par2);
}

offtopic:
Gebruik [code=c], syntax highlighting


Het enige waar ik dan echt altijd mee zit, is regel 5. Of het (*arr)[a] of *(arr[a]) is, of dat het beide werkt en daarmee *arr[a] ook goed is. Omdat je een array op (*arr) zet, zou (*arr)[a] goed moeten zijn, maar dat weet ik echt nooit zeker :P


Overigens, nog opbouwende kritiek op je code, en hoe je uiteindelijk ook kunt zien dat wat jij hebt gewoon fout zou moeten gaan:
C:
5
*dim2= (float *)malloc(sizeof(float)*sizeDim2);

*dim2 is een float*. Je cast malloc dus naar het goede resultaat.

Je wil een array van float*'s malloccen (om daarna een array van floats erin te malloccen). Sizeof(float) is dus fout, het moet sizeof(float*) zijn, aangezien je een array of float*'s wil hebben. Nu is dat zo goed is altijd wel 4, aangezien je vaak genoeg een 32 bits float hebt op een 32 bits systeem (en daarmee 32 bits pointers), maar het *kan* fout gaan.

Daarmee doe je het, als je terug gaat, ook fout. Aangezien je een array van float* 's hebt, dan is resultaat een float**. Je moet dus malloccen naar een (float **). Dan zou je gewoon dim2 als parameter mee geven. En tsja, dim2 is dan dus by val in plaats van by ref (by pointer in C :P). Vandaar, terugrekenen je je weet gewoon dat je het adres van dim2 mee moet geven :)

C:
8
dim2[a]= (float *)malloc(sizeof(float)*sizeDim1);

*dim2 is hetzelfde als dim2[a], als a 0 is. Daarmee alloceer je twee keer hetzelfde stuk. Ook niet goed dus :)

Acties:
  • 0 Henk 'm!

  • MLM
  • Registratie: Juli 2004
  • Laatst online: 12-03-2023

MLM

aka Zolo

Het lijkt alsof je matrix rechthoekig is, dus dan kan je ook af met een losse malloc. Zie onderstaamd voorbeeld. Dit gaat waarschijnlijk performanter zijn (indirectie minder, 1 chunk geheugen is cache-vriendelijker) en gebruikt minder geheugen (geen pointer voor elke rij of kolom) en veiliger (boundschecking mbv assert in debug mode)
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
typedef struct tag_matrix
{
  unsigned width, height;
  float *data;
} matrix;

matrix *create_matrix(unsigned width, unsigned height)
{
  assert(width > 0 && height > 0);
  matrix *m = malloc(sizeof(matrix));
  if(0 == m) return 0;
  m->width = width;
  m->height = height;
  m->data = malloc(width * height * sizeof(float));
  if(0 == m->data)
  {
    free(m);
    return 0;
  }
  return m;
}

void destroy_matrix(matrix *m)
{
  assert(m);
  free(m->data);
  free(m);
}

float get_matrix(matrix *m, unsigned x, unsigned y)
{
  assert(m && x < m->width && y < m->height);
  return m->data[x + y * m->width];
}

void set_matrix(matrix *m, unsigned x, unsigned y, float value)
{
  assert(m && x < m->width && y < m->height);
  m->data[x + y * m->width] = value;
}

[ Voor 18% gewijzigd door MLM op 05-12-2008 10:50 ]

-niks-


Acties:
  • 0 Henk 'm!

  • blackangel
  • Registratie: April 2002
  • Laatst online: 22:25
@MLM.

Dat kan ook, een erg nette manier zelfs. Nadeel is wel dat je zo'n 'library'-gebruik krijgt. Alles moet in functies, terwijl een array benaderen prima zonder functies kan. En set_matrix(m, x, y, value); komt bij mij veel minder duidelijk over dan gewoon m[x][y]=value;

Wel erg afhankelijk van de gebruiker, maar ik zou het zelf niemand aanraden voor het gebruik van een 'gewone' array :)

offtopic:
create_matrix moet natuurlijk return m; hebben.

edit:
Al aangepast zie ik :)

edit:
nog een puntje: die 'error handling' in create moet er wel in zitten ja. Goed punt :)

[ Voor 12% gewijzigd door blackangel op 05-12-2008 11:12 ]


Acties:
  • 0 Henk 'm!

  • MLM
  • Registratie: Juli 2004
  • Laatst online: 12-03-2023

MLM

aka Zolo

blackangel schreef op vrijdag 05 december 2008 @ 10:55:
@MLM.

Dat kan ook, een erg nette manier zelfs. Nadeel is wel dat je zo'n 'library'-gebruik krijgt. Alles moet in functies, terwijl een array benaderen prima zonder functies kan. En set_matrix(m, x, y, value); komt bij mij veel minder duidelijk over dan gewoon m[x][y]=value;

Wel erg afhankelijk van de gebruiker, maar ik zou het zelf niemand aanraden voor het gebruik van een 'gewone' array :)

offtopic:
create_matrix moet natuurlijk return m; hebben.

edit:
Al aangepast zie ik :)

edit:
nog een puntje: die 'error handling' in create moet er wel in zitten ja. Goed punt :)
Mja, je hebt wel een punt, ik vind het zelf ook niet echt lekker om voor elke set/get een functieaanroep te moeten doen. Ik werk dan ook in C++ waar ik wel gewoon een [] operator heb om te overloaden en dan alsnog boundschecking kan doen :P Beste uit beide werelden :)

-niks-


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 02:49

.oisyn

Moderator Devschuur®

Demotivational Speaker

blackangel schreef op vrijdag 05 december 2008 @ 10:29:
Wat je dan ook eigenlijk zou moeten doen, is iets als:
C:
1
2
3
4
5
6
void func(float *** arr, int par1, int par2) {
  int a;
  *arr = (float **)malloc(sizeof(float *)*par1);
  for(a=0;a<par1;a++)
    (*arr)[a] = (float *)malloc(sizeof(float)*par2);
}

offtopic:
Gebruik [code=c], syntax highlighting
Het hele idee dat je een pointer naar de variabele die naar de matrix gaat wijzen moet meegeven is natuurlijk een beetje onzin. Haal die arr parameter weg en retourneer gewoon de matrix uit de functie
C:
1
2
3
4
5
6
7
float ** func(int par1, int par2)
{
  float ** arr = malloc(sizeof(float *)*par1);
  for(int a=0;a<par1;a++)
    arr[a] = malloc(sizeof(float)*par2);
  return arr;
}

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!

  • blackangel
  • Registratie: April 2002
  • Laatst online: 22:25
Voorbeeldje van basiskennis, doorgaan op de topicstart en een voorkeur van implementeren. Jouw manier werkt ook wel, maar dan maakt het mijn methode niet onzin. Dit geeft mij duidelijkheid, zodra ik een create(&m); heb, weet ik dat ik ook een destroy(m);m=NULL; moet doen :)

Je hebt gelijk dat het "moeten" daar verkeerd staat, het moet "kunnen" zijn :)


Btw:
Mallocs moet je typecasten. Jouw code zal op C noch C++ compiler werken, daar "for(int a..." C++ is, en C++ eist dat je typecast. Voor C hoeft het niet, maar ik merk dat het makkelijker debuggen is :)

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 02:49

.oisyn

Moderator Devschuur®

Demotivational Speaker

blackangel schreef op vrijdag 05 december 2008 @ 14:40:
Jouw manier werkt ook wel, maar dan maakt het mijn methode niet onzin.
Dat zei ik ook niet. Ik zei dat een extra parameter die je louter als output-waarde gebruikt, terwijl je return type verder void is an sich een beetje onzin is. Daarmee wil ik niet jouw voorbeeld afbranden, noch zeggen dat je dat nooit moet gebruiken. Daarmee wilde ik iets aan de topicstarter verduidelijken (dat hij momenteel waarschijnlijk dingen voor hemzelf moeilijker aan het maken is dan het is). Als dingen onzin of evil zijn betekent dat niet dat je dat nooit moet doen. Dat betekent dat je er goede redenen voor moet hebben om het te gebruiken (en die heb jij), maar dat lijkt me bij de TS allerminst het geval :).

Overigens:
Mallocs moet je typecasten.
Alleen in C++, mijn code was C.
Jouw code zal op C noch C++ compiler werken
Mijn code werkt op een moderne C compiler
daar "for(int a..." C++ is
Onzin (en dit is wel echt onzin :P), werkt in C sinds 1999. Lees de standaard er nog eens op na zou ik zeggen ;) (specifiek 6.8.5/1 en 6.8.5.3/1), of probeer het zelf met een fatsoenlijke compiler.

[ Voor 34% gewijzigd door .oisyn op 05-12-2008 15:06 ]

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!

  • blackangel
  • Registratie: April 2002
  • Laatst online: 22:25
offtopic:
Je hebt gelijk :) Ik heb op het moment alleen VC6 bij de hand waar ik fatsoenlijk mee overweg kan, die nog van voor C99 is.

Goed om te weten & fijne site :)
Pagina: 1