[C++] probleempje met pointers..

Pagina: 1
Acties:

  • krietjur
  • Registratie: Februari 2001
  • Laatst online: 16:53

krietjur

Where am I?

Topicstarter
.. gok ik.. ik loop altijd te etteren met pointers namelijk.. :) Hier komt 't probleem:

Ik heb (ff versimpeld) dit stukje code:
code:
1
2
3
4
int* TForm1::bereken(){
    int x[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
    return x;
}

Ergens anders in 't programma doe ik vervolgens dit:
code:
1
2
int* uitkomst = bereken();
verwerk(uitkomst);

De methode verwerk ziet er dan als volgt uit:
code:
1
2
3
4
5
void TForm1::verwerk(int* i){
    for(int a=0;a<=5;a++){
      uitvoer[a]->Text=i[2];
    }
}

Dit laatste stukje zorgt ervoor dat de integers die in de array staan op 't scherm komen..
Daarin zit niet 't probleem.. zoals je ziet heb ik er i[2] staan, 'k druk nu dus gewoon een aantal keer
die ene integer op 't scherm. Maar helaas, dat doet ie niet :) De eerste keer wel, maar daarna gooit ie in plaats van de
3 die er moet staan dit op het scherm: 1093683176.

Hoe wat waar waarom?! Zal vast wel weer een domme fout over 't hoofd zien, maar wat :?

  • Hu9o
  • Registratie: Mei 2001
  • Laatst online: 14:21

Hu9o

Schokkend

omdat je nu opvraag wat de waarde van de pointer is, en niet opvraag wat de waarde van de variabele is waar de pointer heen wijst.

Met pascal is moet je namelijk er dan een ^ voor zetten, zodat hij doorheeft dat het gaat om de waarde van de variabele en niet om de waarde van de geheugen lokatie.

Ik kan niet zeggen hoe het moet in c++ want daar heb ik geen ervaring mee. Maar ik herken wel het probleem.

>>>>>>>>>>>>>>>>>>>>>>>>>Vertel Microsoft over dit probleem <<<<<<<<<<<<<<<<<<<<<<<<<


  • marcusk
  • Registratie: Februari 2001
  • Laatst online: 26-09-2023
Variabelen die je hebt gedeclareerd (dus geheugen dat is gealloceerd) in een functie kun je niet daarbuiten, dus dit is niet geldig:
code:
1
2
3
4
int* TForm1::bereken(){
    int x[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
    return x;
}

Ik weet niet welke compiler gebruikt, maar hij zou eigenlijk een warning moeten geven.

Om dit probleem op te lossen moet je x dus globaal declareren. Je kunt ook malloc of new gebruiken om het geheugen te alloceren. dan moet je echter free/delete niet vergeten :)

Verder is je code wel correct zover ik kan zien, dus dat wat Hu9o zegt klopt niet ;)

  • cire
  • Registratie: April 2000
  • Laatst online: 26-07 08:40

cire

 

Wat doet:

uitvoer[a]->Text=i[2];


??

  • krietjur
  • Registratie: Februari 2001
  • Laatst online: 16:53

krietjur

Where am I?

Topicstarter
'k gebruik Borland Builder, en hij geeft inderdaad een warning (Suspicious pointer conversion.)


uitvoer[a] is een array met TEdit dingen erin, waar ik dus die integers inzet.

  • Tomatrix
  • Registratie: Juni 1999
  • Laatst online: 27-02-2025
Volgens mij alloceer je het array x in de mthode 'bereken' op de stack en niet op de heap. Gebruik new of malloc en he t zou moeten werken.

Maar ik kan ernaast zitten want ik heb al jaren niets meer met c/c++ gedaan...

edit:
ok, antwoord was al gegeven

  • Infinitive
  • Registratie: Maart 2001
  • Laatst online: 19-09 17:21
code:
1
int x[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};

verander:
code:
1
static int x[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};

Dan blijft de x bestaan buiten je functie (wanneer je de functie nogmaals aanroept zal x _dezelfde_ x zijn als de vorige keer je de functie aanroept). Zo is je pointer in ieder geval geldig, of het je probleem oplost weet ik niet.
Volgens mij alloceer je het array x in de mthode 'bereken' op de stack en niet op de heap. Gebruik new of malloc en he t zou moeten werken.
Ook dat kan, maar dan moet je niet vergeten die array ook weer te free()'en. En je hebt gelijk.

putStr $ map (x -> chr $ round $ 21/2 * x^3 - 92 * x^2 + 503/2 * x - 105) [1..4]


  • curry684
  • Registratie: Juni 2000
  • Laatst online: 04-09 14:38

curry684

left part of the evil twins

Op woensdag 19 september 2001 21:20 schreef marcusk het volgende:
Om dit probleem op te lossen moet je x dus globaal declareren. Je kunt ook malloc of new gebruiken om het geheugen te alloceren. dan moet je echter free/delete niet vergeten :)
[miereneukmode]
Met new en delete krijg je hier problemen, je moet new [] en delete [] gebruiken :)
[/miereneukmode]

Je moet ff de hoofdstukken over heap/stack allocation en scope doorlezen. Je declareert hier op de stack een array met functiescope. Bij het verlaten van de scope waarbinnen het is gedeclareerd, in dit geval het verlaten van de functie, wordt alles dat binnen die scope op de stack staat vrijgegeven. Je geeft echter een pointer terug naar niet-bestaande data binnen je eigen stack, en dit zal dus GEEN directe access violation opleveren zodra je die pointer gebruikt, maar gewoon met willekeurige data komen of (schijnbaar) willekeurige exceptions.

(was dat te volgen? :P )

Professionele website nodig?


  • krietjur
  • Registratie: Februari 2001
  • Laatst online: 16:53

krietjur

Where am I?

Topicstarter
't static toevoegen heeft mun probleem opgelost, en ik zal inderdaad maar es de hoofdstukken over heap/stack allocation en scope doorlezen :) Thnx voor de hulp in elk geval!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 20:00

.oisyn

Moderator Devschuur®

Demotivational Speaker

jammer, hier valt niet veel te benchmarken :P

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.


Verwijderd

Op donderdag 20 september 2001 00:38 schreef OiSyN het volgende:
jammer, hier valt niet veel te benchmarken :P
:) LOL :) Je zou kunnen proberen te benchen wat het verschil is als je geen pointers gebruikt... iets anders kan ik ook niet verzinnen.

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 04-09 14:38

curry684

left part of the evil twins

Op donderdag 20 september 2001 00:38 schreef OiSyN het volgende:
jammer, hier valt niet veel te benchmarken :P
Oeps ja, ik had hier niet mogen posten ;)

Professionele website nodig?


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 20:00

.oisyn

Moderator Devschuur®

Demotivational Speaker

Op donderdag 20 september 2001 01:12 schreef curry684 het volgende:

[..]

Oeps ja, ik had hier niet mogen posten ;)
foei! en dat het een les voor je mogen zijn :)

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.


  • curry684
  • Registratie: Juni 2000
  • Laatst online: 04-09 14:38

curry684

left part of the evil twins

Op donderdag 20 september 2001 00:53 schreef mgfun het volgende:

[..]

:) LOL :) Je zou kunnen proberen te banchen wat het verschil is als je geen pointers gebruikt... iets anders kan ik ook niet verzinnen.
Zoiets?
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
31
32
33
34
35
36
37
38
39
40
41
42
// ------------------------------------------------------------------------
// Test cases
// ------------------------------------------------------------------------

int* StaticPointertje()
{
static int      Array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
return Array;
}

void Kopieren(int* Target)
{
static const int    Array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
memcpy(Target, Array, sizeof(Array));
}

// ------------------------------------------------------------------------
// Main program
// ------------------------------------------------------------------------
        
int main()
{
int    TargetArray[10];

// Define benchmark code
MPrepareBenchmark(10000000);

MBeginBenchmark(StaticPointertje);
  StaticPointertje();
MEndBenchmark;

MBeginBenchmark(Kopieren);
  Kopieren(TargetArray);
MEndBenchmark;

// Wait for keypress before exit
printf("\nPress any key to exit...");
while(!getch());
return 0;
}

// ------------------------------------------------------------------------

Resultaten:
Method 'StaticPointertje' took 1321 milliseconds
Method 'Kopieren' took 2753 milliseconds


En nou kop houwe OiSyN! :P

Professionele website nodig?


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 20:00

.oisyn

Moderator Devschuur®

Demotivational Speaker

heej er is nog geen asm versie :7

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.


  • whoami
  • Registratie: December 2000
  • Laatst online: 22:58
Op woensdag 19 september 2001 21:20 schreef marcusk het volgende:
Variabelen die je hebt gedeclareerd (dus geheugen dat is gealloceerd) in een functie kun je niet daarbuiten, dus dit is niet geldig:
code:
1
2
3
4
int* TForm1::bereken(){
    int x[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
    return x;
}

Ik weet niet welke compiler gebruikt, maar hij zou eigenlijk een warning moeten geven.

Om dit probleem op te lossen moet je x dus globaal declareren. Je kunt ook malloc of new gebruiken om het geheugen te alloceren. dan moet je echter free/delete niet vergeten :)

Verder is je code wel correct zover ik kan zien, dus dat wat Hu9o zegt klopt niet ;)
Waarom zou dat niet kunnen? De declareert een variable in een functie en die functie returned ze. Niets mis mee.
Het probleem dat Hu90 aangaf, is ook het probleem niet.

Probeer dit eens :
code:
1
Label1->Text = IntToStr(i[2])

Dit zou alvast een oplossing moeten zijn voor die warning.

https://fgheysels.github.io/


  • marcusk
  • Registratie: Februari 2001
  • Laatst online: 26-09-2023
Op donderdag 20 september 2001 20:58 schreef whoami het volgende:

[..]

Waarom zou dat niet kunnen? De declareert een variable in een functie en die functie returned ze. Niets mis mee.
Het probleem dat Hu90 aangaf, is ook het probleem niet.
het type van de returnwaarde v/d functie is int *, dus hij geeft een pointer terug naar een array die is gedeclareerd in die functie, en dus niet meer 'bestaat' zodra de functie is afgelopen. Maar dat is al meerdere keren gezegt. Als het type int[10] oid was zou het idd kloppen wat je zegt: dan zou x namelijk gekopieerd worden.
Probeer dit eens :
code:
1
Label1->Text = IntToStr(i[2])

Dit zou alvast een oplossing moeten zijn voor die warning.
Dat stuk code klopt inderdaad ook niet.

  • marcusk
  • Registratie: Februari 2001
  • Laatst online: 26-09-2023
Op donderdag 20 september 2001 01:36 schreef curry684 het volgende:
Method 'StaticPointertje' took 1321 milliseconds
Method 'Kopieren' took 2753 milliseconds
Kun je het ook eens proberen met een globale x? Aangezien ie dan niet ge-return-ed hoeft te worden is het misschien nog iets sneller lijkt mij.

  • whoami
  • Registratie: December 2000
  • Laatst online: 22:58
Op donderdag 20 september 2001 21:15 schreef marcusk het volgende:

[..]

het type van de returnwaarde v/d functie is int *, dus hij geeft een pointer terug naar een array die is gedeclareerd in die functie, en dus niet meer 'bestaat' zodra de functie is afgelopen. Maar dat is al meerdere keren gezegt. Als het type int[10] oid was zou het idd kloppen wat je zegt: dan zou x namelijk gekopieerd worden.
[..]
een pointer naar een array bestaat niet.
code:
1
2
  int* tabel
  tabel = new int[10];

is net zo goed als
code:
1
  int tabel[10]

Als je de tabel zou returnen als je hem op de 2de manier had gedeclareerd, dan zou hij net hetzelfde doen als op de eerste manier. Hij zou ook gewoon het beginadres van de array returnen.
Als je een array als functie-argument gebruikt, dan wordt er ook altijd gebruik gemaakt van het adres van die array. Op die manier worden array's altijd by reference gepassed, en niet by value.
Dat stuk code klopt inderdaad ook niet.
Wat klopt er niet aan? In BCB werkt dit perfect.

https://fgheysels.github.io/


  • marcusk
  • Registratie: Februari 2001
  • Laatst online: 26-09-2023
Op donderdag 20 september 2001 22:25 schreef whoami het volgende:
een pointer naar een array bestaat niet.
huh?
code:
1
2
  int* tabel
  tabel = new int[10];

is net zo goed als
code:
1
  int tabel[10]
Nee: het verschil is dat in het tweede geval het geheugen niet meer gereserveerd is buiten de scope van de functie.
Als je de tabel zou returnen als je hem op de 2de manier had gedeclareerd, dan zou hij net hetzelfde doen als op de eerste manier. Hij zou ook gewoon het beginadres van de array returnen.
Inderdaad, maar het geheugen is niet meer gereserveerd, en de inhoud ervan dus ongedefinieerd!
Als je een array als functie-argument gebruikt, dan wordt er ook altijd gebruik gemaakt van het adres van die array. Op die manier worden array's altijd by reference gepassed, en niet by value.
Dat is waar ja, dus dit neem ik terug:
Als het type int[10] oid was zou het idd kloppen wat je zegt
---
Wat klopt er niet aan? In BCB werkt dit perfect.
Ik had het hier over: :)
code:
1
uitvoer[a]->Text=i[2];

  • whoami
  • Registratie: December 2000
  • Laatst online: 22:58
Jij wil dus zeggen dat het volgende ook niet zou gaan?
code:
1
2
3
4
5
6
int functie ()
{
 int x;
 x = 10;
 return x;
}

Want hier zou die x dus ook niet meer bestaan buiten die functie.
Die x wordt gewoon gekopieerd naar een andere variable.

https://fgheysels.github.io/


  • whoami
  • Registratie: December 2000
  • Laatst online: 22:58
Op donderdag 20 september 2001 22:37 schreef marcusk het volgende:

[..]

huh?
[..]
Neen, want een array kun je eigenlijk zelf al als een pointer beschouwen.
Stel, je hebt dit:
code:
1
int tabel[100];

tabel (de naam vd array dus), verwijst dan naar het beginadres van die array. Je kan dus evengoed een element op deze manieren benaderen:
code:
1
2
3
x = tabel[i];
// is net hetzelfde als:
x = *(tabel + i)

https://fgheysels.github.io/


  • marcusk
  • Registratie: Februari 2001
  • Laatst online: 26-09-2023
Op vrijdag 21 september 2001 07:46 schreef whoami het volgende:
Jij wil dus zeggen dat het volgende ook niet zou gaan?
code:
1
2
3
4
5
6
int functie ()
{
 int x;
 x = 10;
 return x;
}

Want hier zou die x dus ook niet meer bestaan buiten die functie.
Die x wordt gewoon gekopieerd naar een andere variable.
*zucht*
Hier wordt x inderdaad gekopieerd. In het geval van een array en een int * return-type echter wordt de pointer naar die array gekopieerd, niet de array zelf.
een pointer naar een array bestaat niet, [...] want een array kun je eigenlijk zelf al als een pointer beschouwen
Zie je hoe onlogisch het is wat je zegt?

Verwijderd

Op vrijdag 21 september 2001 07:48 schreef whoami het volgende:
code:
1
2
3
x = tabel[i];
// is net hetzelfde als:
x = *(tabel + i)
[mierenneukerij]

je bedoelt waarschijnlijk
code:
1
x = *(tabel + i*sizeof(<tabel_object_type>);

;)

[/mierenneukerij]

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 20:00

.oisyn

Moderator Devschuur®

Demotivational Speaker

Op vrijdag 21 september 2001 10:42 schreef beelzebubu het volgende:

[..]

[mierenneukerij]

je bedoelt waarschijnlijk
code:
1
x = *(tabel + i*sizeof(<tabel_object_type>);

;)

[/mierenneukerij]
nee, hij deed het goed
tabel is een int *, als je bij pointers integers gaat optellen, dan wordt automatisch rekening gehouden met de grootte van een element
Je telt dus elementen, en geen bytes

tabel + 5 is dus hetzelfde als &tabel[5]

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.


Verwijderd

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>
int main()
{
  int *bla1, *bla2;
  int i;
  bla1 = bla2 = (int *)malloc(sizeof(int)*5);
  for (i=0;i<5;i++)
    bla1[i] = i*20;
  bla2 += 4;
  printf("%d, %d\n", bla1[0], bla2[0]);
  free(bla1);
  return 0;
}
[21 Sep - rbultje@tux /tmp]# ./bla_x
0, 80
[21 Sep - rbultje@tux /tmp]#

Okee, you're right.... Dat wist ik nog niet.... (ik gebruik dit toch alleen met *char's :))

  • whoami
  • Registratie: December 2000
  • Laatst online: 22:58
Op vrijdag 21 september 2001 09:27 schreef marcusk het volgende:

[..]

*zucht*
Zucht, zucht, zucht,... neen, niet zucht.

Er is niets mis met
code:
1
2
3
4
5
int* returnfunctie()
{
  int tabel[10];
  return tabel;
}

https://fgheysels.github.io/


  • marcusk
  • Registratie: Februari 2001
  • Laatst online: 26-09-2023
Op vrijdag 21 september 2001 17:16 schreef whoami het volgende:
Er is niets mis met
(code)
dan mag jij mij uitleggen:
- waarom vc++ deze warning geeft:
warning C4172: returning address of local variable or temporary.
- hoe/wanneer het geheugen van x/tabel vrijgegeven wordt.

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 04-09 14:38

curry684

left part of the evil twins

Op vrijdag 21 september 2001 17:46 schreef marcusk het volgende:
dan mag jij mij uitleggen:
- waarom vc++ deze warning geeft:
warning C4172: returning address of local variable or temporary.
- hoe/wanneer het geheugen van x/tabel vrijgegeven wordt.
Tja dat mensen het concept pointers niet helemaal snappen is jammer genoeg een gegeven achter C/C++, maar dat ze vervolgens een heel stel postings lang hun ongelijk niet willen accepteren kan best irritant worden... |:(

Voor whoami dus: een hard pointer, dus zo'n dingetje met een sterretje, is op een hedendaagse computer altijd 4 bytes groot, en is geen smart pointer, oftewel bij het uit scope raken ervan wordt het object waar hij naar wijst niet automatisch gedelete. Tevens houdt hij aan de andere kant dus ook niet het object waar hij naar wijst automatisch vast. Ter illustratie probeer het volgende programma eens uit:
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
int* ReturnFunctie()
{
int   l_Tabel[5] = {0, 1, 2, 3, 4};
return l_Tabel;
}

void PrintUitArray(int* p_Array, int p_Index)
{
printf("Getal %d is %d\n", p_Index, p_Array[p_Index]);
}

int main()
{
int   l_Index;

for(l_Index = 0; l_Index != 5; l_Index++)
  {
  PrintUitArray(ReturnFunctie(), l_Index);
  printf("Getal %d is %d\n", l_Index, ReturnFunctie()[l_Index]);
  }

while(!getch());
return 0;
}

Als je nu denkt dat hier netjes 2 keer de getallen 0 tot 4 uitkomen heb je het mis, want de output is (bij VC++ en licht compilerafhankelijk):
code:
1
2
3
4
5
6
7
8
9
10
Getal 0 is -858993460
Getal 0 is 0
Getal 1 is -858993460
Getal 1 is 1
Getal 2 is -858993460
Getal 2 is 2
Getal 3 is -858993460
Getal 3 is 3
Getal 4 is 1245056
Getal 4 is 4

Beredeneer maar eens goed...

Professionele website nodig?

Pagina: 1