Pointer auf Array 2 of int



  • MatzeHHC schrieb:

    int arr[2];
    int (*p2)[2]; // ist ein Pointer auf ein array mit 2 int
    p2 = &arr; // ist die Adresse des arrays. Vom Wert her gleich, aber andere bedeutung
    

    Ja und vor allen Dingen UB bei Dereferenzierung von p2. "...andere Bedeutung..." verharmlost solche sinnfreien Zuweisungen.



  • Also würde schon

    p2 = arr

    Stimmen, gell?



  • Wenn der Compiler bei Zeigerzuweisungen im entsprechenden Warn-Modus nicht "incompatible pointer type" meldet, hast du gute Chancen, das richtig gemacht zu haben.
    Meldet der Compiler sowas, ist es eine (leider weit verbreitete) Deppen-Unsitte, diese Meldung durch einen Zeiger-Cast zu umgehen.



  • Hab alles nur online probiert mit ideone, hab momentan leider nicht mehr zur Hand. Leider kamen weder bei der einen noch bei der anderen Variante Meldungen bei mir. Glaub aber eher das es an meiner Bedienung scheiterte.

    Auf jeden Fall danke an alle. Nö an fast alle 😀😀



  • Tja, zu früh gefreut. Compiler motzt.
    Wie würde die Zuweisung richtig aussehen?



  • Jetzt kapier ich es gar nicht mehr.

    P=&arr

    Funktioniert ohne Compiler Fehler und es stürzt auch nicht ab.... UB evtl doch nicht?


  • Mod

    Von welchem Typ ist denn das Ergebnis eines Adressoperators angewendet auf ein int[2]?



  • Ursprünglich hätte ich jetzt gesagt das es die Adresse eines int[2] arrays ist und somit auch passt.
    Aber Wutz (und der kennt sich aus) hatte ja geschrieben das es falsch ist wegen UB. Vielleicht stehe ich jetzt auch auf dem Schlauch, das macht mich jetzt echt fertig.


  • Mod

    pointer_frage schrieb:

    Aber Wutz (und der kennt sich aus) hatte ja geschrieben das es falsch ist wegen UB. Vielleicht stehe ich jetzt auch auf dem Schlauch, das macht mich jetzt echt fertig.

    Ich weiß auch nicht, was er an der Stelle damit meinte. Vielleicht hat er irgendwo in dem langen Thread etwas anders verstanden, als es gemeint war. (Wobei ich hoffe, dass ich selber nichts übersehen habe)



  • Vielleicht äußert er sich ja nochmal dazu. Ich lass mich leicht verunsichern, ich mach das noch nicht so lange, das wissen oder Unwissen ist noch nicht so gefestigt



  • int arr[2];
    int (*p)[2];
    p = &arr;
    

    ist natürlich richtig.

    Wutz meinte lediglich, dass ich deutlicher hätte schreiben sollen, dass es total falsch ist das & weg zu lassen. Auch wenn es den selben Wert liefert, führt p = arr zu undefiniertem Verhalten. Also blos nicht machen ⚠



  • pointer_frage schrieb:

    Aber Wutz (und der kennt sich aus)

    Oder auch nicht.



  • MatzeHHC schrieb:

    int arr[2];
    int (*p)[2];
    p = &arr;
    

    ist natürlich richtig.

    Die Zuweisung (p = &arr) ist durchaus richtig.

    Allerdings macht die Deklaration mit Sicherheit nicht das, was der TE erwartet. p ist ein Zeiger auf ein int[2] array, und somit liefert p[0] die Adresse des ersten Array's, p[1] die Adresse des zweiten Array's usw. :

    printf("%p\n", p[0]);                  // Adresse von arr
        printf("%p\n", p[1]);                  // Adresse von arr + sizeof(int[2])
        printf("%d\n%d\n", p[0][0], p[0][1]);  // Werte arr[0] und arr[1]
    


  • Hatte eigentlich vor, nicht mehr in diesem Thread zu antworten, weil mir das zu kindisch wurde - aber weil Wutz seinen Autismus nicht behandeln lässt, mache ich das eben doch.

    An den OP:

    1. Online-Compiler? Ja klar. m( DAS ist die Zukunft, ganz bestimmt.
    Zur Information: jeder ORDENTLICHE Compiler wirft hier eine Warnung. Weil die Typen unterschiedlich sind Der gcc wirft hier eine. Deiner nicht. Also ist deiner nicht ordentlich.[/virtuellerSchwanzvergleich]

    Jetzt kann man darüber streiten, wie man die Warnung wegbekommt.
    Eine Möglichkeit, die Warnung zu eliminieren, ist die &array -Methode. Die kann effektiv sein. Muss sie aber nicht. Schon gar nicht in deinem Post, in dem Informationen fehlen. Wo wir so überhaupt nicht wissen, was du eigentlich willst, außer deine finale Aussage, die überhaupt keinen Sinn ergibt.

    Eine weitere Möglichkeit ist ein Cast.
    Wie MatzeHHC schon geschrieben hat, gibt es keinen eigentlichen Unterschied zwischen array und &array . Die Adresse des Arrays ist gleichzeitig die Adresse des ersten Elementes des Arrays. Ein Cast sagt dem Compiler nur, dass er die Fresse halten soll.

    Oder eine weitere Möglichkeit ist die Analyse des Programms und die Feststellung, dass es hier keinen Grund gibt, ein Array von Zeigern auf Arrays zu verwenden. Das wäre besser rübergekommen, wenn du eine Referenzierung wie unten beschrieben verwendet hättest.
    Da Zeiger ein komplexes Thema sind und dein Code nach Anfänger schreit, bin ich davon ausgegangen, dass du etwas versucht hast, was du nicht verstanden hast. Eigentlich gehe ich sogar davon aus, dass du es immer noch nicht weißt.

    2. Ist es MEIN Problem, wenn du eine kaputte Kommunikation an den Tag legst? Ich zitiere dich:

    p ist ein Pointer auf ein Array von 2 Int, scheitert es an der zuweisung?

    Das war der zentrale Punkt. Deine Aussage, was in deiner Vorstellung p ist, wie du es anwenden willst. Und das ist falsch. Ich bin mir sicher, du hast mein Beispiel nicht mal kompiliert? Eine Ein-Zeichen-Änderungen, die immer noch mit deiner zentralen Aussage kollidiert, war dir lieber? Ich weiß bisher immer noch nicht, ob du Zeiger nur nicht korrekt verstanden hast (wovon ich immer noch ausgehe, weil ich bei der Dereferenzierung des Zeigers t[x][x] machen würde anstatt (*t)[x] - weil du ein Array von Zeigern auf Arrays hättest statt einen Zeiger auf ein Array).

    3. DU willst mir Deklarationen erklären? Du, der es selbst nicht schafft, seine Deklarationen zu erklären? Ich glaub, es hackt.

    Klugscheißer

    Und warum werden wir gleich beleidigend?
    Du hast Glück, keinen angemeldeten Account zu verwenden, sonst käme der in mein Killfile. Jedenfalls hast du gerade die Chance eliminiert, dass ich dir in diesem Thread nochmal helfe.

    An Wutz:

    Ich meine das Ernst, irgendwas stimmt mit dir nicht.
    Wenn du mit einer Aussage von mir nicht übereinstimmst, SAG ES, und schreib nur nicht, dass ich falsch liegen würde. Ich erinnere dich an deine Aussage in einem anderen Thread, dass es keinen Unterschied machen würde, ob man unsigned int* oder unsigned char* verwendet. Ich habe damals ganz genau widersprochen und gesagt, WIESO es einen Unterschied macht. Mit Beispiel und dem Fehler, den es verursacht.

    Mit allem, was ich von dir jemals bekommen habe, kann ich meinen Garten düngen. Also sag an, was Sache ist. Mit "ist falsch" kann ich nichts anfangen, mit "halt die Klappe" schon gar nicht. Nein, weißt du was, sag nichts *into the killfile it goes*.

    An osdt: +1.


  • Mod

    dachschaden schrieb:

    Eine weitere Möglichkeit ist ein Cast.
    Wie MatzeHHC schon geschrieben hat, gibt es keinen eigentlichen Unterschied zwischen array und &array . Die Adresse des Arrays ist gleichzeitig die Adresse des ersten Elementes des Arrays. Ein Cast sagt dem Compiler nur, dass er die Fresse halten soll.

    Ich bekomm's gerade nicht hin, aber irgendwie ist es bestimmt möglich ein Beispiel zu basteln, wo man damit auf die Fresse fliegt*. Es sind inkompatible Pointertypen. Einen davon in den anderen zu casten und danach lesend darauf zu zu greifen ist undefiniertes Verhalten. Basta.

    *: Vielleicht irgendwas mit Unions und zusammengesetzte Typen mit ungerader sizeof, bei gleichzeitig strikten Anforderungen ans Alignment. virtual in all seinen Ausprägungen wäre sicher auch ein guter Kandidat, wenn man C++ in Betracht zieht. Irgendwie gibt es bestimmt eine Kombination, das falsch zu biegen.



  • Dann solltest du dir in keinem Fall die ganzen sockaddr -Typen anschauen. Da macht man ständig Casts von sockaddr_in* bzw. sockaddr_in6* oder auch mal sockaddr_un* . Sind alle untereinander zuweisbar. connect übernimmt zum Beispiel immer nur sockaddr* . Machbar isses auf jeden Fall. Wenn du einen Fehler findest - die glibc-Leute werden sich freuen. 🙂 Oder vielleicht auch die gcc-Leute, wenn du eine Stelle findest, wo sie das Alignment falsch machen.


  • Mod

    Dass das in diesen Fällen funktioniert und auch immer funktionieren wird, bestreit ich gar nicht. Ich bin bloß ebenso sicher, dass man irgendwie einen Fall konstruieren kann, wo die Aussage, dass es egal wäre, ob man arr oder &arr schreibt, zu Problemen führt.

    (Und dass das Casten von inkompatiblen Pointertypen Probleme verursachen kann, ist trivial zu zeigen.)



  • Mein Post bezog sich auf deine dann doch verallgemeinerte Aussage:

    SeppJ schrieb:

    Es sind inkompatible Pointertypen. Einen davon in den anderen zu casten und danach lesend darauf zu zu greifen ist undefiniertes Verhalten.



  • @dachschaden: Es ist nicht naheliegend, daß jemals ein Compiler den UB-Code nicht korrekt übersetzt. Eigentlich.
    Aaber, anscheinend benutzt der GCC gelegentlich die schärfstmögliche Auslegung des Standards, um UB-Stellen zu finden und wegzuoptimieren. Also irgendwann kriegen sie Dich.

    SeppJ schrieb:

    Ich bin bloß ebenso sicher, dass man irgendwie einen Fall konstruieren kann, wo die Aussage, dass es egal wäre, ob man arr oder &arr schreibt, zu Problemen führt.

    Der einer Funktion übergebene Wert ist ja gleich. Da sehe ich wenig Spielraum, eine Funktion in Produktivcode zu schmuggeln, um z.B. openssl wieder aufzumachen.

    #include <stdio.h>
    #include <string.h>
    
    //fills any object with zeros.
    //#define INIT_ZERO(x) memset(x,0,sizeof(*(x)))
    #define INIT_ZERO(p) testMemset(p,0,sizeof(*(p)))
    
    void testMemset(void* p,int v,size_t n){
    	printf("memset(%p,%u,%zu)\n",p,v,n);
    }
    
    int main() {
    	struct{
    		int arr[10];
    	} str;
    	int arr[10];
    
    	INIT_ZERO(&str);//ok
    
    	INIT_ZERO(&arr);//ok
    
    	//INIT_ZERO(str);//Compilerfehler
    //error: invalid type argument of unary '*' (have 'struct <anonymous>')
    
    	//Als alter C-Hase weiß ich ja, daß ich vor Arrays in Aufrufen
    	//das & immer weglassen darf. Außer, SeppJ und volki zetteln 
    	//eine Verschwörung an…
    	INIT_ZERO(arr);//Kein Compilerfehler. 
    //Löscht leider nur 4 Bytes statt 40. 
    
    	return 0;
    }
    


  • @Volkard:
    Jau, bin ich bereit, anzuerkennen. Danke dafür.


Anmelden zum Antworten