char*-array an Funktion übergeben



  • Hallo,

    Ich habe ein Problem mit einem char*-array, welches ich an eine Funktion übergeben möchte.
    Innerhalb der main()-Funktion bin ich in der Lage, die korrekte Anzahl von Elementen im array zu ermitteln (1. out-stream).
    Sobald ich das array jedoch an Eine Funktion übergebe, geht scheinbar ein string-element verloren (2. out-stream). Kann mir jemand helfen, wo mein Denkfehler liegt?

    #include <iostream>;
    
    using namespace std;
    
    void funct1(char* array1[]) {
    	int elements=sizeof(array1) / sizeof(array1[0]);
    	cout << elements << endl;
    }
    
    int main() {
    	char* char_array[]={"String1","String2"};
    	int elements=sizeof(char_array) / sizeof(char_array[0]);
    
    	cout << elements << endl;
    	funct1(char_array);
    }
    


  • Der sizeof -Operator prüft lediglich die Grösse des Objekts. In der Funktion hast du kein Array mehr, sondern nur noch einen Zeiger. sizeof(array1) ist die Grösse des Zeigers, wahrscheinlich 4 Byte.

    Du musst die Grösse also zusätzlich übergeben. Arbeite zudem besser mit const char* statt char* , weil du sonst aus Versehen leicht in verbotenen Speicher schreiben kannst.

    void func1(const char** array, unsigned int size);
    
    // Anmerkung: In der Parameterdeklaration sind folgende Schreibweisen 
    // äquivalent, es handelt sich immer um Zeiger auf Zeiger auf char:
    const char array[][]
    const char* array[]
    const char** array
    

    Alternativ arbeitest du mit den Möglichkeiten von C++, std::vector<std::string> - das ist viel einfacher und sicherer zu handhaben. Aber ich weiss nicht, wie weit du hier schon bist. Für reine Stringliterale wie "String1" ist const char* okay. Sobald du jedoch beginnst, mit strcpy() und solchen Dingen was hinzufrickeln, wäre std::string eine Überlegung wert.



  • array1 ist innerhalb der Funktion nur ein Pointer, und zwar ein char**.

    Warum tun sich Leute immer die scheiß Frickelei mit Arrays und char* an wenns Container und Strings gibt?

    #include <iostream> //semikolon hinterm include ist sinnlos
    #include <string>
    #include <vector>
    
    using namespace std;
    typedef vector<string> stringvec;
    
    void funct1(stringvec const& sv) {
    	cout << sv.size() << endl;
    }
    
    int main() {
    	stringvec sv(2);
            stringvec[0] = "String1"; 
            stringvec[1] = "String2";
    	int elements=sv.size();
    	cout << elements << endl;
    	funct1(sv);
    }
    

    und wenn dir das Füllen des vectors nicht so recht schmecken mag schau dir boost::assign an 🙂



  • In der Funktion hast du kein Array mehr, sondern nur noch einen Zeiger.

    Das Array wird also als solches gar nicht an die Funktion übergeben, sondern nur ein Zeiger auf das Array, welches selbst ja wieder mit char* gefüllt ist.

    *char[0], oder **char
    

    wäre dann also die entsprechende Dereferenzierung zum 1. String, auch innerhalb der Funktion?

    Arbeite zudem besser mit const char* statt char*, weil du sonst aus Versehen leicht in verbotenen Speicher schreiben kannst.

    Ist durch die Initialisierung der Form

    char*a={"String"}
    

    der String selbst nicht automatisch konstant?
    Ich habe mich nämlich an dieser Stelle gewundert, dass der Compiler an der Stelle des Input-Arguments meiner Funktion nicht auf

    const char* array1[]
    

    bestanden hat.



  • Martin2000 schrieb:

    Ist durch die Initialisierung der Form

    char*a={"String"}
    

    der String selbst nicht automatisch konstant?
    Ich habe mich nämlich an dieser Stelle gewundert, dass der Compiler an der Stelle des Input-Arguments meiner Funktion nicht auf

    const char* array1[]
    

    bestanden hat.

    De facto ist er konstant, ja. Aber aus historischen Gründen sind string-Literale nicht vom Typ const char* sondern nur char*. Du kannst den pointer also rumreichen und irgendwo nichtsahnend darein schreiben und dich wundern warum dir das Programm um die Ohren fliegt. Der Compiler bemängelts jedenfalls nicht.



  • Meiner Meinung nach würde diese Fragestellung nicht so oft auftauchen, wenn es in C nicht die Syntax char array[] für die Übergabe eines Zeigers an eine Funktion gäbe. Warum hat man das gemacht? Es ist eine Zeigerübergabe, und die wäre mit einem * wesentlich offensichtlicher.

    In C++ gibt es aber die Möglichkeit, eine Referenz auf ein Array unter Erhaltung (oder bessergesagt, der zusätzlichen Angabe) der Größeninformation zu übergeben. Diese Größeninformation wird beim Compilieren durch Inferenz ermittelt. Das kann manchmal durchaus sinnvoll sein, für Strings und Container stimme ich allerdings pumuckl zu, sind std::string und std::vector meist weitaus sinnvoller.



  • Martin2000 schrieb:

    Das Array wird also als solches gar nicht an die Funktion übergeben, sondern nur ein Zeiger auf das Array, [...]

    Nein. Ein Zeiger auf das erste Element des Arrays, also ein Zeiger vom Typ char** . Ein Zeiger auf Dein Array wäre vom Typ char*(*)[2] .

    Nochmal:

    void foo1( char dings[] );
    void foo2( char * dings );
    

    sind äquivalent. Bedanken kann man sich dafür bei dem Erfindern von C.

    Außerdem, benutzt Du eine veraltete Konvertierung Stringliteral --> char*, welche nur aus C-Kompatibilitätsgründen unterstützt wird. Da man Stringliterale aber nicht ändern kann/darf, solltest Du const char* nehmen -- wenn überhaupt.


Anmelden zum Antworten