Frage zu Array in Funktionen



  • Hallo, wie kann ich in der Funktion ermitteln wie viele Elemente der Parameter hat ?

    main()
    {
    char ar[200];
    t ( ar );
    
    return 0;
    }
    
    int t ( char v[] )
    {
    
    char a[200];
    
    cout<<sizeof(v)<<endl;  // Gibt immer 4 aus
    
    cout<<"a: " << sizeof(a)<<endl;  // Gibt 200 aus 
    
    return 0;
    }
    


  • array schrieb:

    Hallo, wie kann ich in der Funktion ermitteln wie viele Elemente der Parameter hat ?

    Garnicht. Arrays "zerfallen" bei der Übergabe an Funktionen zu Pointern auf das erste Element. Deshalb auch sizeof(v) == 4, weil Pointer auf deinem System immer die Größe 4 haben. Alle Info, wieviele Elemente da tatsächlich hinter hängen, geht verloren.
    Benutze Container an Stelle der Arrays, dann klappts auch 🙂



  • Geht nicht. Entweder du übergibst die Größe als Parameter, oder du benutzt:

    * std::array / boost::array wenn die Größe zur Compilezeit bekannt ist.
    * std::vector, wenn die Größe dynamisch ist.

    Dein Code mit std::array :

    template<std::size_t Size>
    void t(std::array<char, Size>& arr)
    {
      std::cout << arr.size() << "\n";
    }
    
    int main(int argc, char** argv)
    {
      std::array<char, 200> arr;
      t(arr);
    }
    

    Mit std::vector:

    void t(std::vector<char>& vec)
    {
      std::cout << vec.size() << "\n";
    }
    
    int main(int argc, char** argv)
    {
      std::vector<char> vec(200);
      t(vec);
    }
    


  • Bei Array-Typen gibt es eine nicht-intuitive Sonderbehandlung an diversen Stellen. Schnapp Dir am besten ein richtiges Buch und lerne damit.

    Eine dieser Sonderbehandlungen ist zB, dass der Compiler jeden Parametertypen T[] oder T[N] in der Parameterliste einer Funktion durch T* ersetzt. v ist also nur ein dummer Zeiger. Die Initialisierung, die hier stattfindet, nennt sich "copy initialization":

    void foo(char *v);
    
    char a[200];
    char *ptr = a; // hier wird ptr genauso
    foo(a);        // wie v initialisiert.
    

    Wenn Du eine Zeigervariable so wie hier mit einem Array-Ausdruck initialisierst, dann zeigt der Zeiger einfach auf das erste Array-Element.

    Ob Du also als Parametertypen char v[] oder char*v hinschreibst, ist Jacke wie Hose.

    Trotzdem: Zeiger sind Zeiger und keine Arrays. Arrays sind Arrays und keine Zeiger. Du kannst aber mit einem Zeiger und dem []-Oprator auf Array-Elemente zufgreifen. Das funktioniert deswegen, weil zeiger[index] als Abkürzung für *(zeiger+index) definiert wurde und weil Array-Elemente hintereinander im Speicher liegen.



  • Du kannst statt direkt das Array zu übergeben auch eine Adresse darauf übergeben, damit kann der Compiler die sizeof Information ermitteln:

    typedef char MeinTyp[200];
    
    void f(MeinTyp *a)
    {
      cout << sizeof(*a) << endl << *a << endl;
    }
    
    int main()
    {
      MeinTyp a = { "bla fasel" };
      f(&a);
      return 0;
    }
    

  • Mod

    Das fiese ist aber, die Funktion funktioniert dann nur mit 200er Arrays. Wie in Pascal.



  • Kapierst du wahrscheinlich nicht aber so geht es mit C-Arrays:

    #include <iostream>
    #include <cstddef>
    template<class T, std::size_t Size>
    std::size_t CArraySize(T(&)[Size])
    {
      return Size;
    }
    int main()
    {
      int Foo[123];
      std::cout << CArraySize(Foo);
    }
    


  • EOutOfResources schrieb:

    Kapierst du wahrscheinlich nicht aber so geht es mit C-Arrays:

    #include <iostream>
    #include <cstddef>
    template<class T, std::size_t Size>
    std::size_t CArraySize(T(&)[Size])
    {
      return Size;
    }
    int main()
    {
      int Foo[123];
      std::cout << CArraySize(Foo);
    }
    

    Da ist doch wohl meine Lösing mit std::array eleganter.



  • Ethon schrieb:

    Da ist doch wohl meine Lösing mit std::array eleganter.

    Klar, aber meine Antwort passt auf seine Frage, deine nicht 😉 .



  • krümelkacker schrieb:

    Bei Array-Typen gibt es eine nicht-intuitive Sonderbehandlung an diversen Stellen. (...)

    Eine dieser Sonderbehandlungen ist zB, dass der Compiler jeden Parametertypen T[] oder T[N] in der Parameterliste einer Funktion durch T ersetzt.*

    Ich wollte nur nochmal die IMO wichtigste Info hier hervorheben, da das etwas ist, wo vermutlich fast jeder Anfänger drüberstolpert.


Log in to reply