Hallo, ich habe noch ein Problem: eine Funktion liest 256 Words vom I/O ein. Der Funktion wird ein Zeiger eines Arrays vom Typ uint16_t übermittelt. Die eingelesenen Daten werden dort reingeschrieben. Also z.B.: void readio(uint16_t *Buffer) { for(i=0; i<256; ++i) { *Buffer=readwordio(); Buffer++; } } Das funktioniert auch wunderbar: uint16_t IrgendeineVar[256]; readio(IrgendeineVar); Das Problem ist, dass ich manchmal Statusdaten einlesen will. Die möchte nicht in ein uint16_t Var[256] bekommen, sondern in ein typedef struct statusdaten { uint16_t Status1; uint16_t Status2; ... }; struct statusdaten IrgendeineVar; readio(IrgendeineVar); funktioniert ja nicht. Ist es möglich, dass man der Funktion Zeiger eines beliebigen Datentyps übergeben kann (vorrausgesetzt die Länge der Datentypen ist gleich)?
Also zur Not gibt es da immernoch ein void*. Damit kann man eigentlich alles übergeben ... 1 > void readio(uint16_t *Buffer) { 2 > for(i=0; i<256; ++i) { 3 > *Buffer=readwordio(); 4 > Buffer++; 5 > } 6 > } Das Problem liegt bei Dir in Zeile 4. Der ++Operator benötigt die Größe des Feldes, damit er weiß, wie weit er gehen soll :-) Es gibt also 2 Möglichkeiten: 1. in readio() wieder mit typ (z.B. uint16_t) casten und anschließend ++ benutzen. 2. statt ++ die Adresse von Buffer selber um die Länge des Types erhöhen. (sizeof()) Falls Du structs verwenden willst, geht eigentlich nur Methode 2. Besser wäre meiner Ansich nach z.B. ein case in readio() mit zwei verschiedene Routinen - A für Daten, B für Statusinfos. Könnte sein, dass ein "schlauer" Compiler, dann eh das tut, was Du ihm aufzwingen willst. Keine Ahnung. Aber Du bist erstmal auf der sicheren Seite ...
Halb-OT: Wenn man ganz korrekt ist, kennt C gar kein 'call by reference', ausschließlich 'call by value'. Funktions-Parameter werden in jedem Fall als Wert, also als Kopie, übergeben. Ob der Parameter ein int oder ein Zeiger ist, spielt keine Rolle. Echtes 'call by reference' kennt erst C++: void foo(int& i); int i = 2; foo(i); Hier wird der Parameter wirklich als Referenz übergeben, eine Kopie findet (semantisch) nirgendwo statt.
Diese Referenzen sind das, was mir an C++ unangenehm auffällt (und nicht nur dort, in Pascal* ist da ja auch schon so gewesen). Beim Funktionsaufruf foo(i) kann man -ohne sich den Prototypen von foo() näher anzusehen- nicht herausfinden, ob i verändert wird oder nicht. Da ist mir die "gute alte" Pointer-Schreibweise doch deutlich lieber. Bei der ist es eindeutig, was geschieht, ohne daß man den Prototypen ansehen muss: foo(&i); Auch führt hier eine einseitige Änderung des Funktionsprototypens oder des Funktionsaufrufes zu einem Fehler - was bei einer Referenz nicht der Fall wäre. Allerdings lässt sich das Überladen der Operatoren nicht ohne Referenzen implementieren; daher sind die Dinger gerechtfertigt. *) ich muss das nicht mögen. "Wer nichts wird, wird Wirth" (trollbait)
> Allerdings lässt sich das Überladen der Operatoren nicht ohne > Referenzen implementieren; daher sind die Dinger gerechtfertigt. Nicht nur das, auch ein Copy-Konstruktor wäre ohne Referenzen schwer möglich. Ich finde, bei Referenzen überwiegen die Vorteile eindeutig die Nachteile. Zum Beispiel Klassen (etwa einen großen string) werden in C++ selten by value übergeben, einfach aus dem Grund, weil das Kopieren "ewig" dauern würde. Dafür gibts die schöne Schreibweise foo(const string&) anstelle foo(string). In C müsste man in so einem Fall gleich wieder mit Zeigern hantieren, was den Funktionsaufruf doch etwas unintuitiver macht. ...aber das war ja gar nicht die Frage des OPs, merk' ich gerade. ;-)
Tatsächlich ist es nicht allzu schlimm, wenn man einen C++ string by value übergibt, weil das eigentliche string Objekt nur einen Zeiger auf die eigentlichen Zeichendaten enthält. Bei einer Zuweisung von einem string zu einem anderen hat man dann zwei strings, welche auf dieselben Zeichendaten verweisen. Das ist kein Problem, weil die string Objekte mit Hilfe von Reference Counting wissen, wieviele Objekte auf die Zeichendaten zeigen. Wird eine Operation auf einem string ausgeführt, welche die Zeichendaten ändert, legt der string eine eigene Kopie der Zeichendaten an, falls mehr als ein string auf sie verweist (Copy on Write Schema). Dies ist natürlich kein Grund, keine konstanten Referenzen zu verwenden, wenn möglich.
> Tatsächlich ist es nicht allzu schlimm, wenn man einen C++ string > by value übergibt, weil das eigentliche string Objekt nur einen > Zeiger auf die eigentlichen Zeichendaten enthält. Natürlich enthält ein string nur einen Zeiger auf die Daten. Ein normaler C-String ist nunmal ein char*, also ein normaler Zeiger. Allerdings wird beim Kopieren eines string-Objekts nicht nur dieser Zeiger kopiert (flat copy), sondern die ganzen Daten (deep copy). Das, was du beschreibst, nennt man auch "lazy operations", also verzögert ausgeführte Operationen. Allerdings ist mir keine string-Implementation bekannt, die diese Methode benutzt. p.s.: grr Jetzt durfte ich diesen Beitrag wieder mehrmals schreiben, weil das Forum mein Posting nicht immer beim ersten Mal annimmt.
>Natürlich enthält ein string nur einen Zeiger auf die Daten. Ein >normaler C-String ist nunmal ein char*, also ein normaler Zeiger. Ich rede nicht von C-Strings, sondern von der Klasse string (bzw. der Templateklasse basic_string) der C++ Library. Soweit ich weiss arbeitet z.B. die Implementation der libstdc++ mit einem Verfahren ähnlich dem das ich oben beschrieben habe.
> Ich rede nicht von C-Strings, sondern von der Klasse string (bzw. der > Templateklasse basic_string) der C++ Library. Ich auch. Ok, meine Aussage war vielleicht etwas missverständlich. Einige string-Implementationen benutzen aber soweit ich weiß intern C-Strings, also char*. Dadurch vereinfacht sich dann std::string::c_str() ziemlich, aber auf Kosten anderer string-Methoden. sizeof(std::string) ist bei jeder Implementation konstant, allein aus dem Grund muss die string-Klasse ja schon einen Zeiger auf den eigentlich String enthalten. So hab ich das gemeint. :)
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.