Zeiger und Vektoren



  • @wob sagte in Zeiger und Vektoren:

    Hm... Wenn 4 / 4 = 1 ist, dann ist 8 / 4 = ?

    1 Rest 4 ??



  • Die Ausgabe von i ändert sich. Ich habe das Array3 vor Übergabe an die Funktion mit: int arr3[5]; definiert.
    Damit hat es funktioniert, wie ich bei einer weiteren Ausgabe des Arrays3 in Merge gesehen habe. Bin die Funktion
    zuvor immer im Schrittbetrieb durchgegangen und habe den Mauszeiger auf array3 in Merge gehalten. So habe
    ich komischerweise immer nur einen Eintrag des Arrays3 gesehen. Hätte erwartet, dass auch im Einzelschrittbetrieb mir
    alle Einträge eines Arrays angezeigt werden.



  • Du hättest das Array mit int arr3[5] = {0}; gleich initialisieren können (da werden auch nicht aufgeführte Elemente auf 0 gesetzt)
    Und in main nochmal eine Schleife mit Ausgabe zur Kontrolle.



  • Ich habe inzwischen die Übersicht verloren. Wie ist dein vollständiger Code? Wo ändert sich die Ausgabe von i? (Schrittbetrieb & Mauszeiger halten sind Dinge deiner Entwicklungsumgebung - da ists schwierig darüber zu sprechen)

    Warum machst du nicht etwas in der folgenden Art:

    int min(int a, int b) {
        if (a < b) return a;
        return b;
    }
    
    int merge(int arr1[], int arr2[], size_t n, int arr3[])
    {
        for (size_t i = 0; i < n; ++i) {
            arr3[i] = min(arr1[i], arr2[i]);
        }
    }
    


  • So geht es natürlich auch. Interessanter vom Lerneffekt fand ich trotzdem die Zeiger. Vielen Dank!



  • @C-Sepp Dann schreib statt Zeile 9
    *arr3++ = min(*arr1++, *arr2++);



  • Ich bin noch ein weiteres Codesbeispiel durchgegangen. Bei diesen wird ein string s mittels der Funktion strtok() in
    Teilzeichenfolgen zerlegt, welche durch Zeichen aus dem String delim begrenzt werden. Die Funktion lautet:
    char* strtok(char* s, const char* delim)

    Zum Lernen habe ich mir diese Funktion so in etwa mal nachprogrammiert, wobei wieder ein paar
    Fragen entstanden sind, welche wahrscheinlich trivial sind:

    char** test(char* s1, const char* s2)
    {
        s1 = "ein anderer Test"; //Fehlerconst char [17]" kann nicht in "char *" konvertiert werden
        s2 = "Test1";
        s2 = "Test2"; 
        return &delim;
    }
    
    int main()
    { 
        char s1[] = "Das ist ein Test";
        char s2[] = "Das ist ein anderer Test";
    
        test(s1,"Das ist ein anderer Test");
    }
    

    Warum kann ich den Read-Only-Zeiger s2 in der Funktion eigentlich beliebige Werte zuweisen? (Wäre dies
    ein Zeiger auf Integer wäre dies nicht möglich.)
    Warum kann ich s1 hingegen keinen Wert zuweisen? Nochmals vielen Dank!



  • Die Fehlermeldung kommt, weil ein String-Literal in C++ (also sowas in "doppelten Quotes") ein konstanter String ist. Diesen kannst du nicht verändern. (das ist auch ein Unterschied von C++ zu C, wo es auch ohne const ginge)

    Die Zuweisung an s2 funktioniert, weil bei s2 eben const dransteht. Du musst unterscheiden: ist der Zeiger konstant oder ist das, auf das der Zeiger zeigt, konstant? Mit const char * hast du einen (veränderbaren) Zeiger auf einen konstanten char. Verwechsle das nicht mit char * const (const hinter dem *) - dann wäre der Zeiger konstant, aber nicht das, auf das der Zeiger zeigt. Und mit const char * const wäre sowohl der Zeiger als auch das, auf das der Zeiger zeigt, konstant. Du kannst auch char const * bzw. char const * const schreiben, also das const und char vertauschen, was in letzter Zeit populärer geworden ist (nennt sich east const / west const).

    Du kannst hier "C Gibberish" nach Englisch übersetzen: https://cdecl.org/?q=const+char+*c

    Abgesehen davon folgendes:

    • delim ist nicht bekannt (Zeile 6)
    • wozu übergibst du überhaupt s1 und s2 als Parameter, wenn du mit s1 = ... und s2 = ... deren Werte als allererstes versuchst zu überschreiben?




  • Super...wieder etwas dazugelernt. Gut zu wissen auch, dass der Schreibschutz eines konstanten Zeigers im Gegensatz zu strings nicht unterlaufen werden kann. Sprich ich kann einen konstanten Zeiger keinen nicht konstanten Zeiger zuweisen:

    unsigned int strlen(const char *s)
    {
        ...
        char* temp = s; // Fehler
    }
    
    const string s1 ="Ein Stringstest";
    string s2 = s1;
    

    Dass der Aufruf der oben definierten Funktion test auch mit test(s1, s2) in der Main funktioniert, hängt dann wahrscheinlich konkret damit zusammen, dass s2 nach Zuweisung des Strings "Das ist ein anderer..." ein konstanter String ist?



  • Zu Testzwecken habe ich die Funktion test auch nochmal verändert:

    const char** test(const char* const s1, const char* s2)
    {    
        s1 = "ein anderer Test";   //Fehler
        s2 = "Test1";   
        s1 = s2; //Fehler  
       
        return &s1; //Fehler
    }
    

    Beide Zeiger sind jetzt konstant und zeigen auf ein Objekt, welches selbst konstant ist. Wie erwartet erscheinen in den Zeilen 3 und 5 jetzt Fehler. Warum Zeile 7 auch nicht passt, ist mir nicht klar. Ich hole mit & die Adresse des doppelt konstanten Zeigers s1. Also lese/hole nur die Adresse. Warum stimmt der Rückgabetyp nicht mit den Funktionstyp überein (Fehler)? Dank!!!



  • @C-Sepp sagte in Zeiger und Vektoren:

    Warum stimmt der Rückgabetyp nicht mit den Funktionstyp überein (Fehler)? Dank!!!

    Der genaue Wortlaut der Fehlermeldung wäre doch angebracht.
    Per Copy&Paste.

    Andererseits bringt das auch nichts, da s1 eine lokale Variable ist, die beim Beenden der Funktion (das macht return) nicht mehr existiert.
    Die Adresse davon ist nicht sinnvoll.



  • Die Fehlermeldung lautet:
    "const char *const *" kann nicht in "const char **" konvertiert werden



  • Dann ist const char *const * was du als Rückgabetyp angeben solltest.

    Ist aber nicht sinnvoll.



  • @C-Sepp sagte in Zeiger und Vektoren:

    Super...wieder etwas dazugelernt. Gut zu wissen auch, dass der Schreibschutz eines konstanten Zeigers im Gegensatz zu strings nicht unterlaufen werden kann. Sprich ich kann einen konstanten Zeiger keinen nicht konstanten Zeiger zuweisen:

    ???

    const string s1 ="Ein Stringstest";
    string s2 = s1;
    

    Das hier in Zeile 2 erzeugt eine KOPIE von s1! s1 wird nicht geändert und somit auch kein const-Schutz unterlaufen! Die Kopie in s2 kannst du natürlich ändern. Das änder aber nicht s1.

    In diesem Code:

    char* temp = s; // Fehler
    

    Hier machst du keine Kopie des Strings, sondern versuchst, den Pointer zu kopieren, aber nicht den String selbst. Wenn das erlaubt wäre, würdest du durch Ändern von temp[0] auch s[0] ändern.

    Auch mit char-Pointern darfst du natürlich Kopien anlegen. Dies muss aber mit strcpy oder verwandten Funktionen geschehen. Und dann darfst du auch const nach nicht-const kopieren.



  • Okay!
    Wenn bei char* temp = s nur der Zeiger kopiert wird, warum erscheint dann in dem Fall (Zeiger auf konstantes Objekt) eine Fehlermeldung, welche das const ankreidet??
    Das heißt wenn Pointer und Wert kopiert werden würden, könnte ich durch Ändern von temp[0] auch s[0] ändern, obwohl nur eine Kopie angelegt wird...wie geht denn das. Das entspricht doch eigentlich den Prinzip einer Referenz??



  • Nein, es wird keine Kopie des Strings angelegt, sondern nur der Zeiger (die Adresse) kopiert. Und weil ein String-Literal ("...") nicht verändert werden kann, mußt du einen const char * verwenden (also dessen Inhalt dann eben nicht per z.B. Indexoperator verändert werden kann).



  • @C-Sepp sagte in Zeiger und Vektoren:

    Das heißt wenn Pointer und Wert kopiert werden würden, könnte ich durch Ändern von temp[0] auch s[0] ändern, obwohl nur eine Kopie angelegt wird...wie geht denn das.

    Nein, wenn Du auch den Wert kopierst, ist

    temp[0] != s[0]
    

    kopierst Du nur den Zeiger, ist

    temp[0] == s[0]
    

    Der Wert ist ja dann nur einmal vorhanden, es wird aber von zwei verschiedenen Zeigervariablen drauf gezeigt.



  • Hey Leute,

    bin auf eine Funktion gestoßen, zu der sich eine Frage ergeben hat. Sie lautet:

    double* Summe(double* a, double* b, int length)
    {
        double* sum = new double[length];
        for (int i=0; i<length; i++)
        {
           sum[i] = a[i] + b[i];
        }
        return sum;
    }
    

    Addiert also Schritt für Schritt die Werte zweier an a und b übergebener Array's. Warum kann ich mit a[i] und b[i] die Werte zur Addition ansprechen? Eigentlich wurde bei Zeigern doch immer der *-Operator verwendet. Vielen Dank!



  • Der Indexoperator a[n] ist äquivalent zu *(a + n).

    Alternativ kann man auch die Funktion so deklarieren:

    double* Summe(double a[], double b[], int length)
    

    Wie du siehst, kein Unterschied zwischen Array- und Zeigerzugriff.


Anmelden zum Antworten