Zeiger auf zeiger = CRASH!!



  • sheddy schrieb:

    aber warum ich int nehmen soll, verstehe ich irgendwie immer noch nicht! 😞

    Die Funktion int main() wird vom C-Startcode aufgerufen und wenn main beendet ist, nimmt der nach

    call _main
    

    folgende Code an, der zufällig im CPU-Register EAX (=32 Bit, int = 32 Bit) stehende Wert sei der absichtlich an den Aufrufer (meist das Betriebssystem) zurückzugebende Wert.

    Info: Rückgabewerte werden in C grundsätzlich über das Register EAX zurückgeliefert.



  • aaaaaaaaaaaaaachso....
    das einzige, was ich eben verstanden habe ist

    Die Funktion int main() wird vom C-Startcode aufgerufen...

    😃

    aber ich werde es in "int" umändern und ein "return 0;" ranhängen!!

    Aber bei der Schleife für die beiden dynamischen arrays kannste mir nicht helfen,ne?!

    ich weiß einfach nicht weiter, wie ich die umschreiben soll.

    for(i=0;i<n;i++)
        {
             for(k=0;k<(n/2);k++)
             {
               if(array[i]%2==0)
                   *evens[k]=array[i];
               else    
                  *odds[k]=array[i];        
             }
        }
    

    Das geht ja auch nicht!

    Ich müsste ja irgendwie ne Überpfüung haben, ob das erste Element der beiden Arrays schon besetzt ist oder ich muss irgendwie aus der zweiten for-schleife rauspringen, ohne dass beim nächsten durchlauf der zähler zurück auf 0 gesetzt wird! (aber dann gibt es wieder stress mit dem zweiten dynamischen array! 😞 )



  • Nach dem Prinzip müsste es funktionieren (ich weiß jetzt nicht genau, ob *odd eingeklammert werden muß):

    int o, e;
    
    o = e = 0;
    for (i = 0; i < n; i++)
        if (array[i]%2 == 0)
            *odd[o++] = array[i];
          else
            *even[e++] = array[i];
    


  • also beim ersten schleifen-durchlauf macht er beginnt er trotzdem noch bei 0 und DANN wird der Zähler erhöht,ne?!



  • o++ wird *danach* erhöht, geht also bei 0 los
    ++o würde bei 1 losgehen.

    Edit: Falls die Frage auftaucht for (;; i++) ist egal "for (;; ++i) geht auch



  • keksekekse schrieb:

    for (;; i++)

    Und das dürften auch die gängigsten Compiler schön brav optimieren 😉



  • keksekekse schrieb:

    sheddy schrieb:

    aber warum ich int nehmen soll, verstehe ich irgendwie immer noch nicht! 😞

    Die Funktion int main() wird vom C-Startcode aufgerufen und wenn main beendet ist, nimmt der nach

    call _main
    

    folgende Code an, der zufällig im CPU-Register EAX (=32 Bit, int = 32 Bit) stehende Wert sei der absichtlich an den Aufrufer (meist das Betriebssystem) zurückzugebende Wert.

    Info: Rückgabewerte werden in C grundsätzlich über das Register EAX zurückgeliefert.

    es gibt andere Architekturen als i386 😉

    Moderne Betriebsysteme erkennen anhand des Rückgabewertes eines Programms (Rückgabe von int main() bzw. explizit durch exit() festgelegt), ob der Prozess fehlerhaft oder nicht beendet wurde. Wenn man 0 zurückliefert, dann ist der Prozess fehlerlos beendet, etwas ungleich 0 sonst.

    Damit so Sachen funktionieren können wie

    $ (prog1 && prog2) || prog3
    

    müssen die Programme prog1,prog2, prog3 auch mitteilen, wie sie beendet wurden, denn prog2 kann nur dann ausgeführt werden, wenn prog1 fehlerlos beendet wurde und prog3 nur dann, wenn prog1 oder prog2 fehlerhaft terminierten.

    Außerdem definiert das Standard, dass main von Typ int sein muss und basta, alles andere ist somit falsch!



  • okay, danke schön! habe das jetzt mit intz main() einigermaßen verstanden!

    Und mein Programm läuft auch!
    Falls es noch jemanden interessiert, es sieht jetzt so aus:

    void Partition (int array[], int n, int **evens, int *numEvens, 
                                        int **odds, int *numOdds)
    {
    	int i,k,p;
    	k=p=0;
    	for(i=0;i<n;i++)
    	{
    		if(array[i]%2==0)
    			(*numEvens)++;
    		else
    			(*numOdds)++;
    
    	}
    
    	(*evens)=(int*)malloc((*numEvens)*sizeof(int));
    	(*odds)=(int*)malloc((*numOdds)*sizeof(int));
    
    	for(i=0;i<n;i++)
    	{
    		if(array[i]%2==0)
    		{
    			(*evens)[k]=array[i];
    			k++;
    		}
    		else
    		{
    			(*odds)[p]=array[i];
    			p++;
    		}
    
    	}
    
    }
    

    Vielen Dank



  • sheddy schrieb:

    Und mein Programm läuft auch!
    Falls es noch jemanden interessiert, es sieht jetzt so aus:

    auf den ersten blick scheint das aber nicht die optimalste lösung in bezug auf geschwindigkeit zu sein 😉



  • du könntest es auch so machen:

    int **optr=odds;
    int **eptr=evens;
    //...
    for(i=0; i<n; ++i)
        {
            if(array[i]%2==0)
                 **(eptr++)=array[i];
            else
                 **(optr++)=array[i];
        }
    

    und noch was: auch wenn nicht gefordert, ein

    assert(*evens && *odds)
    

    (assert.h) oder if-abfrage+exit() nach dem malloc solltest du schon noch mit reinbringen.



  • das mit der optimierung habe ich mir auch schon gedacht, wusste es abe rnicht besser.

    Ich weiß jetzt nicht genau, was du da gemacht hast! Ich komme nämlich ein wenig durcheinander mit den Zeigern!

    Mit dem einfachen Zeiger, also der Übergabe einer Variablen durch dessen Adresse an eine andere Funktion habe ich verstanden!

    main
    int x;
    2fkt(&x)

    void 2fkt(*y)

    *y=... (Zugriff auf die Zelle)
    y=... (Zugriff auf die Adresse)

    Das ist noch relativ einfach!
    Bei doppelten Zeiger muss ich es doch dann genau so machen,oder?! Muss eben nur ein Stufe höher denken oder?!

    Und dann komme ich völlig ins tüdeln mit den arrays! Bei einfachen Zeigern, die auf ein Array zeigen, kann ich ja das Sternchen ("*") weglassen, weil das erste Element ja eh ein Zeiger ist, der aufs erste zeigt!

    Aber wie das beim doppelten Zeiger ist..hmmm! Habe das eigentlich aus dem Bauch heraus gemacht!

    Eigentlich sollte doch auch dies funktionieren (sollte):

    for(i=0;i<n;i++)
        {
            if(array[i]%2==0)
            {
                (evens)[k]=array[i]; /*Sternchen weg, weil es ja eh ein Zeiger aufs este Element ist*/
                k++;
            }
            else
            {
                (odds)[p]=array[i]; /* Hier das gleiche */
                p++;
            }
    
        }
    

    Naja...ich wollte eigentlich nur sagen, dass ich zeiger und dynamische Speicherverwaltung erst eine Vorlesung hatte und ich froh bin, soweit gekommen zu sein. Deshalb verstehe ich auch nicht so recht, was das mit "assert" auf sich hat! Ich lass meine Aufagebe erst mal von meinem Prof überprüfen! Mal sehen, was er dazu sagt!

    Aber trotzdem danke für deine Hilfe!



  • Hier mal ein schönes Beispiel wie man mit Zeigern auf Zeiger arbeitet:

    RegexPart* RegexAddPart(RegexPart** ppRegexPart)
    {
    	if(ppRegexPart == NULL)
    		return NULL;
    	while(*ppRegexPart != NULL)
    		ppRegexPart = &(*ppRegexPart)->Next;
    	*ppRegexPart = new RegexPart;
    	return *ppRegexPart;
    }
    [...]
    RegexPart* FirstRegexPart = NULL;
    RegexPart* CurrentRegexPart = NULL;
    CurrentRegexPart = RegexAddPart(&FirstRegexPart);
    


  • das val++ und ++val wird dir auch noch begegnen aber irgendwie habe ich das gefühl das das programm noch immer nicht richtig läuft, zumindest erhalte ich weiterhin den von dir berschriebenen fehler. übrigens: assert(bedingung) besteht eben darauf dass der teil "bedingung"==true ist. sollte das nicht so sein wird das programm mittles abort() abgebrochen. das ist deshalb wichtig da es ja sein könnte das die speicherallokierung (malloc()) fehlgeschlagen ist. dann kannst du den speicher natürlich nicht verwenden. du könntest auchschreiben

    if(*evens && *odds)//speicher erfolgreich reserviert?
    {
       //code...
    }
    else
       exit(1);
    


  • ah, okay...

    Aber das Programm funktioniert soweit! Es gibt keine Fehler oder Abstürze wie am Anfang.
    Der komplette Code sieht wie folgt aus (als "C-Code kompilieren"):

    #include<stdio.h>
    #include<stdlib.h>
    
    /*void CountEvensAndOdds ( int array[], int n, int *numEvens, int *numOdds); */
    void Partition (int array[], int n, int **evens, int *numEvens, 
                                        int **odds, int *numOdds)
    {
    	int i,k,p;
    	k=p=0;
    	for(i=0;i<n;i++)
    	{
    		if(array[i]%2==0)
    			(*numEvens)++;
    		else
    			(*numOdds)++;
    
    	}
    
    	(*evens)=(int*)malloc((*numEvens)*sizeof(int));
    	(*odds)=(int*)malloc((*numOdds)*sizeof(int));
    
    	for(i=0;i<n;i++)
    	{
    		if(array[i]%2==0)
    		{
    			(*evens)[k]=array[i];
    			k++;
    		}
    		else
    		{
    			(*odds)[p]=array[i];
    			p++;
    		}
    
    	}
    
    }
    
    int main ( void )
    { 
       int arr[] = {7,4,13,8};
       int *evens, *odds; //Zeiger Felder mit den ungeraden und geraden Zahlen.
       int numEvens = 0; 
       int numOdds = 0, i = 0;
    
       Partition(arr, 4, &evens, &numEvens, &odds, &numOdds);
    
       printf("Das Feld enthaelt %d gerade und %d ungerade Zahlen\n", numEvens, 
              numOdds);
       printf("Ausgabe der geraden Zahlen: \n");
       for(i=0; i < numEvens; i++)
          printf("%d\n", evens[i]);
       printf("Ausgabe der ungeraden Zahlen: \n");
       for(i=0; i < numOdds; i++)
          printf("%d\n", odds[i]);
    
       // Felder fuer die geraden und ungeraden Zahlen liegen auf dem Heap und 
       // muessen freigegeben werden.
       free(evens);
       free(odds);
       return 0;
    }
    


  • @sheddy
    Die Abfrage von $noopy solltest du noch einbauen.


Anmelden zum Antworten