Archief - [PROG][C] Pointer decl. in main, alloc. in functie, niet returnen. foute opgave?

Het archief is een bevroren moment uit een vorige versie van dit forum, met andere regels en andere bazen. Deze posts weerspiegelen op geen enkele manier onze huidige ideeën, waarden of wereldbeelden en zijn op sommige plaatsen gecensureerd wegens ontoelaatbaar. Veel zijn in een andere tijdsgeest gemaakt, al dan niet ironisch - zoals in het ironische subforum Off-Topic - en zouden op dit moment niet meer gepost (mogen) worden. Toch bieden we dit archief nog graag aan als informatiedatabank en naslagwerk. Lees er hier meer over of start een gesprek met anderen.

tha_rippa1be

Legacy Member
We hebben binnen een paar dagen examen van C en als soort van controle of ge er genoeg van kende was er op Blackboard het examen van vorig jaar gezet.

Maar ik heb een probleempje ergens, en ik denk dat de fout in de opgave zit.
Nu, ik kan het amper geloven aangezien het een examen is geweest dus zou ik het is willen laten controleren.

Het hele project kan hier gevonden worden, lees de punten onder de link voor de vragen/meer info:
http://jeroenpelgrims.be/vanalles/files/exjan.htm
Vooraf: aan de main mag niets gewijzigd worden.
het gaat om de functies maakparade en toonparade
  • Er word in main een int pointer gedeclareerd (lijn 34)
  • Deze wordt dan gebruikt in de functie maakparade die aangeroepen word op lijn 53
  • in maakparade (lijn 117) word deze pointer dan gealloceerd (hij krijgt dus een ander adres in de functie)
  • er worden bewerkingen uitgevoerd op de gealloceerde ruimte (lijn 122-127)
  • Dan word een integer waarde gereturned (deze is nodig in een andere functie)
Het is dan toch onmogelijk om te verwachten dat ge die pointer in andere functies kunt gebruiken?
Hij word nergens gereturned. Het adres blijft dus hetzelfde in de main (zelfde adres als voor de allocatie).
Dus die bewerkingen die er op gedaan zijn hangen vast aan die andere pointer die ge van de malloc gereturned krijgt.

Is dit dan een foute opgave, of zie ik ergens iets over het hoofd?

Tyfius

Legacy Member
Dat is nu net het punt van pointers. Je alloceert met de declaratie op lijn 34 geen geheugen, je vertelt alleen dat er moet rekening gehouden worden met een pointer naar een geheugenlocatie. Momenteel bevat die dus nog niets. Een goeie manier van programmeren is ook de pointer bij de declaratie op NULL te zetten.

Op lijn 117 alloceer je vervolgens een blok geheugen en zorg je ervoor dat die parade pointer naar die locatie verwijst. Doordat je aan de maakparade() functie een verwijzing naar een pointer variabele doorgeeft en geen kopie van een variabele pas je dus rechtstreeks de originele waarde aan (die in dit geval nog niet bestaat of NULL is).

Meer informatie over pointers in C kan je hier vinden.

tha_rippa1be

Legacy Member
Tyfius zei:
Dat is nu net het punt van pointers. Je alloceert met de declaratie op lijn 34 geen geheugen, je vertelt alleen dat er moet rekening gehouden worden met een pointer naar een geheugenlocatie. Momenteel bevat die dus nog niets. Een goeie manier van programmeren is ook de pointer bij de declaratie op NULL te zetten.

Op lijn 117 alloceer je vervolgens een blok geheugen en zorg je ervoor dat die parade pointer naar die locatie verwijst. Doordat je aan de maakparade() functie een verwijzing naar een pointer variabele doorgeeft en geen kopie van een variabele pas je dus rechtstreeks de originele waarde aan (die in dit geval nog niet bestaat of NULL is).

Meer informatie over pointers in C kan je hier vinden.

Dat zou allemaal werken mocht ik de pointer(het adres dat ik terugkrijg van malloc) mogen returnen, maar dat mag dus niet (het adres dat in parade zit in main blijft hetzelfde na het uitvoeren van een malloc in de functie want ik return dat nieuw adres niet).

De parameters en returntypes van de functies staan vast, daar mag ik niks aan veranderen.

Tyfius

Legacy Member
Je moet die toch niet returnen? Die pointer is een verwijzing, die blijft bestaan. Je verandert alleen de waarde.

Het is hetzelfde principe als in het volgende voorbeeld (basis pointer lessen):
Code:
void foo(int *bar) {
  bar += 2;
}

int bar = 0;
foo(bar);
De variabele bar is nu dus 2, zonder dat die gereturned werd.

In jouw oefening is alleen de operatie anders.

tha_rippa1be

Legacy Member
Tyfius zei:
Je moet die toch niet returnen? Die pointer is een verwijzing, die blijft bestaan. Je verandert alleen de waarde.

Het is hetzelfde principe als in het volgende voorbeeld (basis pointer lessen):
Code:
void foo(int *bar) {
  bar += 2;
}

int bar = 0;
foo(bar);
De variabele bar is nu dus 2, zonder dat die gereturned werd.

In jouw oefening is alleen de operatie anders.

ja, maar het gaat om de waarde die de pointer zelf bevat(het adres van bar dus), niet degene naarwaar hij verwijst.

Een verkort voorbeeld wat er eigenlijk gebeurt in die examenoefening:
hopelijk is het dan wat duidelijker wat ik bedoel.

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

void doeiets(int *p){
	p=(int*)malloc(2*sizeof(int));
	*p=5;
	*(p+1)=8;
	//hetgene in p zit (nieuw adres van malloc word niet gereturned, net als in die examenoef)

}
void main(void){
	int *ipointer=NULL;
	doeiets(ipointer);
	printf("%d %d", *ipointer, *(ipointer+1));//fout, ipointer heeft nog geen ruimte gealloceerd gekregen
}

dit werkt wel daarintegen:
PHP:
#include <stdio.h>
#include <stdlib.h>

int * doeiets(int *p){
	p=(int*)malloc(2*sizeof(int));
	*p=5;
	*(p+1)=8;
	//hetgene in p zit (nieuw adres van malloc word niet gereturned, net als in die examenoef)
	return p;
}
void main(void){
	int *ipointer=NULL;
	ipointer=doeiets(ipointer);
	printf("%d %d", *ipointer, *(ipointer+1));//fout, ipointer heeft nog geen ruimte gealloceerd gekregen
}
maar daarvoor moet ik de returnwaarde van doeiets() veranderen en in de main ook iets, wat dus niet mag in die oefening.

Tyfius

Legacy Member
Eens korter gekeken en de oefening gecompileerd.

In de main functie staat 1 fout (geeft een warning normaal):
Code:
aantal = maakparade(haven, "groen", &parade, aantalboten); // fout

aantal = maakparade(haven, "groen", parade, aantalboten); // goed, geen & gebruiken
Hetzelfde geldt voor de andere maakparade() oproep. Als dit zo al in de main() stond die jij gekregen hebt zitten ze met een probleem.

In toonparade() doe je hetvolgende:
Code:
printf("%05d ",*(parade+i));
Hier mag je die * niet gebruiken. Correct is dus:
Code:
printf("%05d ",(parade+i));

tha_rippa1be

Legacy Member
Tyfius zei:
Eens korter gekeken en de oefening gecompileerd.

In de main functie staat 1 fout (geeft een warning normaal):
Code:
aantal = maakparade(haven, "groen", &parade, aantalboten); // fout

aantal = maakparade(haven, "groen", parade, aantalboten); // goed, geen & gebruiken
Hetzelfde geldt voor de andere maakparade() oproep. Als dit zo al in de main() stond die jij gekregen hebt zitten ze met een probleem.

In toonparade() doe je hetvolgende:
Code:
printf("%05d ",*(parade+i));
Hier mag je die * niet gebruiken. Correct is dus:
Code:
printf("%05d ",(parade+i));

Ze zitten met een probleem=het is een fout in de opgave?

hmm, bij u opmerking over toonparade, het is een pointer dat ik aankrijg dus moet ik toch de waarde naarwaar hij verwijst afdrukken? (anders drukt hij het adres dat in de pointer zit af)

Anyways, bedankt voor uw tijd hier in te steken, het is zeer geapprecieerd :)

Tyfius

Legacy Member
Als die main() extact is zoals jij ze hebt gekregen, dan zit er een fout in.

Daarnaast ben ik niet helemaal zeker of de uitwerking van de andere oefeningen volledig correct is. Het lijkt mij allemaal een beetje onlogisch soms, is het mogelijk de opgave ook eens te posten? Ik snap bijvoorbeeld niet echt het nut van die maakparade() functie zoals ze in jouw oefening staat, nog van de toonparade() functie.

tha_rippa1be

Legacy Member
Tyfius zei:
Als die main() extact is zoals jij ze hebt gekregen, dan zit er een fout in.

Daarnaast ben ik niet helemaal zeker of de uitwerking van de andere oefeningen volledig correct is. Het lijkt mij allemaal een beetje onlogisch soms, is het mogelijk de opgave ook eens te posten? Ik snap bijvoorbeeld niet echt het nut van die maakparade() functie zoals ze in jouw oefening staat, nog van de toonparade() functie.

Zeker, link

Het is de bedoeling om de kentekens van boten met een bepaalde kleur op te slagen in een integer array en die dan bij toonparade af te drukken.

-edit-
bij oef 2.5 heb ik die loop niet bijgedaan.
maar voor de rest is die correct

Tyfius

Legacy Member
Bon, ik heb een oplossing.

De declaratie van de functie maakparade() moet je aanpassen om te voldoen, in plaats van een int *parade moet dit een int **parade worden. Dan pas je ook de for-loop aan om de kentekens in te vullen.
Code:
int maakparade(BOOT haven[], char kleur[], int **parade, int aantal){
  int i, pt=0;
 
  *parade = malloc(bepaalaantal(haven, kleur, aantal) * sizeof(int));
 
  for(i = 0; i < aantal; i++){
    if (strcmp(haven[i].kleur, kleur) == 0) {
      (*parade)[pt] = haven[i].kenteken;
      pt++;
    }
  }
 
  return pt; /* Niet pt + 1! */
}

void toonparade(int aantal, int *parade){
  int i;
 
  if(aantal > 0){
    for(i = 0; i < aantal; i++){
      printf("%05d ", *parade + i);
    }
  }else{
    printf("Geen");
  }
}

Opmerking: het is aangeraden om na de malloc() steeds op NULL te controleren of die wel gelukt is, en eventueel een memset() om de waarden op 0 te zetten en de garbage die eventueel nog in het geheugen kan zitten te wissen.

Het resultaat is uiteindelijk goed, of het anders kan en de juiste oplossing qua implementatie, daar ben ik nog niet uit :)

tha_rippa1be

Legacy Member
Da's iets waar ik niet op opgekomen zou zijn met de gedachtengang die ik had.

Fantastisch man, Hartelijk bedankt!
Ik ben niet den enige dat ge geholpen hebt, er waren er nog met het zelfde probleem.

nogis bedankt ;)


Ik denk dat de oplossing volgens de regels van het examen is.
Ge hebt niks veranderd aan de main, en de prototypes van de functies mocht ge zelf invullen.

killgore

Legacy Member
In de main wordt er een pointer naar een pointer meegegeven aan maakParade.

Uw declaratie van maakparade moet dus niet zijn
Code:
int maakparade(BOOT haven[], char kleur[], int *parade, int aantal)
Maar:
Code:
int maakparade(BOOT haven[], char kleur[], int **parade, int aantal)

Immers, in main wordt gedeclareerd int* parade
en je geeft &parade mee, dat is het adres van de pointervariabele zelf, niet het adres waarnaar de pointer wijst :).

En als je dan zo verder redeneert (zoals tyfius blijbkaar gedaan heeft, kheb niet alels gelezen) gaat er niets van je allocatie verloren ;).
Het archief is een bevroren moment uit een vorige versie van dit forum, met andere regels en andere bazen. Deze posts weerspiegelen op geen enkele manier onze huidige ideeën, waarden of wereldbeelden en zijn op sommige plaatsen gecensureerd wegens ontoelaatbaar. Veel zijn in een andere tijdsgeest gemaakt, al dan niet ironisch - zoals in het ironische subforum Off-Topic - en zouden op dit moment niet meer gepost (mogen) worden. Toch bieden we dit archief nog graag aan als informatiedatabank en naslagwerk. Lees er hier meer over of start een gesprek met anderen.
Terug
Bovenaan