Referenz auf Array fester Größe


  • Mod

    es ist in c oder C++ unmöglich, arrays unbestimmter größe als parameter von funktionen zu verwenden. aus diesem einen grunde gibt es eine sonderregel (6.7.5.2/5 in C99 und -kann ich jetzt auf die schnelle für C++ nicht finden). die muss auch zwingend existieren, um diese deklaration zu erlauben, denn ein array unbekannter größe ist ein unvollständiger typ, und unvollständige typen können nunmal nicht für funktionsparameter verwendet werden. diese regel besagt, dass eine deklaration mit[] so behandelt werden soll, als ob sie mit * erfolgt wäre.

    im gegensatz zu skalaren typen, sind arrays stets lvalues - und die übliche implizite wandlung in ein rvalue existiert nicht. es gibt allerdings eine implizite umwandlung in einen (rvalue) pointer auf das erste element.
    und das ist der witz daran:
    wenn der kontext ein rvalue verlangt, dann verhält sich ein array dort, als ob es ein pointer wäre (in diesem kontext kann man diese tatsächlich nicht unterscheiden). und (fast) alle oben genannten beispiele fallen eben in diese katageorie. das beweist aber nicht, das arrays pointer sind, nur das die auswahl der beispiele suboptimal ist.

    es gibt nur wenige kontexte, die ein lvalue brauchen: das brot-und-butter beispiel zuweisung klappt nun leider gerade nicht, denn ich kann arrays nicht zuweisen (eben weil es nichts passendes für die rechte seite mangels rvalue arrays gibt)
    es verbleiben operatoren, die lvalues brauchen:
    & (und wie dein beispiel richtig gezeigt hat: char * p2 = &Array ist das ergebnis eben nicht ein pointer auf char sondern ein pointer auf ein array aus 11 chars).
    sizeof - der klassiker
    zusätzlich:
    initialisierung einer referenz, hier steht rechts vom = zeichen wieder ein lvalue

    jetzt sollte klar sein, warum das

    int array[10];
    int*& ref = array;
    

    nicht geht. zwar kann array implizit in einen pointer auf das erste element, also einen pointer aiuf char gewandelt werden. das ergebnis ist aber ein rvalue, und kann folglich nicht zur initialisierung einer referenz auf (non-const) char verwendet werden.

    edit: viele (bestimmt nicht alle) rechtsschreibfehler beseitigt - heute wieder besonders schlimm



  • Ich würde einigen Leuten hier raten, ihr Grundwissen nochmal zu überprüfen. Besonders die, die Sachen wie

    Ein Array ist ein Zeiger auf den ersten Index...

    Was nen compiler mit ner referenz auf nen Array mit groessenangabe macht, ist sicher nicht definiert, die meisten machen aber nen doofen zeiger draus, also kannst die groesse an der stelle nie draus ermitteln.

    schreiben. Dieses Halbwissen verwirrt Unwissende nur. Und noch schlimmer, auch diese verbreiten dieses Halbwissen dann wieder.



  • Super, wenn ich mir das hier so ansehe, muss ich mich wohl nicht wundern dass alle paar Wochen jemand hier aufschlägt und verzweifelt versucht ein 2D-Array als Zeiger auf Zeiger zu übergeben.



  • Schön, dass ihr euch so nett unterhaltet hier, aber an meinem Problem hat sich leider noch nichts geändert. (http://www.c-plusplus.net/forum/viewtopic-var-p-is-1074379.html#1074379)



  • Neku schrieb:

    Schön, dass ihr euch so nett unterhaltet hier, aber an meinem Problem hat sich leider noch nichts geändert. (http://www.c-plusplus.net/forum/viewtopic-var-p-is-1074379.html#1074379)

    Du könntest einen neuen Typ definieren, wie ich vorgeschlagen habe mit struct oder mit typedef, diesen Typ kannst Du gleichsetzen und auch Referenzen darauf bilden.

    struct MyArray
    {
      char_t Data[256];
    };
    

    Du könntest auch eine Schleife programmieren, die 256 Bytes kopiert.
    Du könntest mit memcopy 256 Bytes kopieren.

    Du kannst nicht Arrays auf Arrays kopieren.


  • Mod

    zeig doch mal die deklaration von WideStringClass::m_FreeTempPtr



  • @Xin: Ich möchte ja eine Referenz auf das Array, anstatt es zu kopieren - darum geht es ja 😉

    @camper:

    class WideStringClass
    {
    
    public:
    
    	static wchar_t* (&m_FreeTempPtr)[256];
    	// ...
    
    };
    


  • Neku schrieb:

    @Xin: Ich möchte ja eine Referenz auf das Array, anstatt es zu kopieren - darum geht es ja 😉

    Wo ist das Problem?

    struct wchar_array256
    {
      wchar_t Data[256];
    };
    
    class WideStringClass
    {
    public:
      static wchar_array256 * m_FreeTempPtr;
    };
    

    Das sollte Dein Problem doch typgerecht lösen, oder?



  • Dann kann ich leider m_FreeTempPtr nicht wie bisher verwenden, sondern muss überall m_FreeTempPtr.Data schreiben. Der Weg über ein Struct ist schließlich etwas zu umständlich. Wenn es nicht direkt über wchar_t*(&)[256] geht, muss ich wieder zu wchar_t** zurückgehen.



  • Neku schrieb:

    Dann kann ich leider m_FreeTempPtr nicht wie bisher verwenden, sondern muss überall m_FreeTempPtr.Data schreiben. Der Weg über ein Struct ist schließlich etwas zu umständlich. Wenn es nicht direkt über wchar_t*(&)[256] geht, muss ich wieder zu wchar_t** zurückgehen.

    Immer diese Extrawünsche 😉

    class wchar_array256
    {
      private:
        wchar_t Data[256];
    
      public:
        wchar_t & operator [] (int index)
        {
          return Data[index];
        }
    };
    
    class WideStringClass
    {
    public:
      static wchar_array256 * m_FreeTempPtr;
    };
    

    Damit kannst Du jetzt auch WideStringClass::m_FreeTempPtr[ foobar ] schreiben.



  • Xin schrieb:

    Damit kannst Du jetzt auch WideStringClass::m_FreeTempPtr[ foobar ] schreiben.

    Ähh.. quatsch... der [] geht hier erstmal auf den Zeiger, nicht auf den Datentyp ^^

    (*WideStringClass::m_FreeTempPtr)[ foobar ]
    

    Mit 'ner Referenz sollte das aber auszubügeln sein, dann fehlt Dir allerdings die Möglichkeit "NULL" zuzuweisen, Du müsstest also eine
    wchar_array256::NULL Instanz haben, sofern Du sie brauchst.

    class WideStringClass
    {
    public:
      static wchar_array256 & m_FreeTempPtr;
    };
    


  • EDIT:
    Zu lahm, hehe



  • wchar_t* wString = this->m_freeTempPtr[x];
    

    So soll das aussehen 😉


  • Mod

    Neku schrieb:

    wchar_t* (&WideStringClass::m_FreeTempPtr)[256] = *(wchar_t*(*)[256])0x00809D40;
    

    Nicht über den Sinn des ganzen nachdenken - ich hätte nur gerne eine Lösung, ob standardkonform oder nicht 😃
    Aktueller Fehler: "error C2101: '&' on constant"

    *edit2*
    Folgendes funktioniert übrigens:

    uint32& uVar = *(uint32*)0x012345678;
    

    das scheint eine beschränkung des compilers zu sein. prionzipiell geht es ja um

    T& foo = *(T*)0x12345678;
    

    für beliebiges skalares T scheint visual c++ das zu akzeptieren. sobald T allerdings ein array ist, erhalten wir den beschriebenen fehler - dabei ist anzumerken, das das problem auf der rechten seite ist. interessanterweise funktioniert das hier immer (und könnte als ausweg dienen):

    T* const foo = (T*)0x12345678;
    T& bar = *foo;
    

    da foo in jedem falle vor bar initialisiert wird, wäre das eine mögliche lösung. ich würde das problem nicht unbedingt als bug unsehen, da das ergebnis des casts, der hier benutzt wird, von vornherein implementationsabhängig ist.



  • Neku schrieb:

    wchar_t* wString = this->m_freeTempPtr[x];
    

    So soll das aussehen 😉

    Das solltest Du mit etwas Phantasie auch noch selber hinbekommen. :-\

    [cpp]
    wchar_t * operator [] (int index)
    {
    return &Data[index];
    }
    [cpp]


Anmelden zum Antworten