Problem mit Pointerarithmetik



  • Weyl schrieb:

    char* ret="";
    char a;
    ret += a;
    

    sehe ich das richtig, dass ich den += operator auch so ausschreiben kann?

    ret = ret + a
    

    Ja.
    Und bedeutet, dass der aktuelle Wert von ret um den aktuellen Wert von a erhöht wird, bzw. wenn a negativ ist, verringert wird. ret repräsentiert also anschließend eine Adresse im Umfeld von CHAR_MIN...UCHAR_MAX vom Ausgangswert, und diese Ausgangsadresse kann auch in einem Readonly-Speicherbereich liegen. (wegen der Initialisierung mit einem String-Literal)



  • vielen dank für eure antworten!

    für mich sieht es so aus, als ob dieser code-snippet von einem anfänger stammt, der von pascal oder ähnlichen sprachen gewöhnt ist, dass man strings einfach addieren kann. macht das sinn?

    DirkB schrieb:

    Ein char ist ein Integer mit einem kleineren Wertebereich.
    Der Bereich ist so gewählt, dass ein char ein Zeichen (charakter) aufnehmen kann.

    also ist ein char auf den meisten üblichen computersystemen ein byte groß, oder?



  • Weyl schrieb:

    also ist ein char auf den meisten üblichen computersystemen ein byte groß, oder?

    Ein char ist so groß, wie ein Byte auf dem jeweiligen System.
    Es gibt auch Systeme die nicht 8 Bit für ein Byte haben.

    Weyl schrieb:

    für mich sieht es so aus, als ob dieser code-snippet von einem anfänger stammt, der von pascal oder ähnlichen sprachen gewöhnt ist, dass man strings einfach addieren kann. macht das sinn?

    Ist das der ganze Code? a ist nicht initialisiert.
    Kennt ein Anfänger denn schon += ?



  • vielen dank für deine rasche antwort, DirkB!

    DirkB schrieb:

    Weyl schrieb:

    also ist ein char auf den meisten üblichen computersystemen ein byte groß, oder?

    Ein char ist so groß, wie ein Byte auf dem jeweiligen System.
    Es gibt auch Systeme die nicht 8 Bit für ein Byte haben.

    dass es auch systeme gibt, wo ein byte nicht 8 bits hat, ist mir klar. auf allen systemen, die ich persönlich kenne, ist das aber so.

    also ist ein char immer ein byte groß, egal, wie groß ein byte ist?

    DirkB schrieb:

    Weyl schrieb:

    für mich sieht es so aus, als ob dieser code-snippet von einem anfänger stammt, der von pascal oder ähnlichen sprachen gewöhnt ist, dass man strings einfach addieren kann. macht das sinn?

    Ist das der ganze Code? a ist nicht initialisiert.
    Kennt ein Anfänger denn schon += ?

    hier ist der ganze code:

    char* getbinfile(char* fn){
        char* ret="";
        char a;
        FILE* fp = fopen(fn,"rb");
        if(fp == NULL){ 
            cout << "failed opening "<<fn<<endl;
            return "";
        }
        //cout << "file length: "<< filelength(fp)<<endl;
        int i = 0;
        while(!feof(fp)){
            a = (char)fgetc(fp);
            ret += a;
            i++;
        }
    //    cout << "read "<< i <<" times"<<endl;
        return ret;
    }
    

    soll wohl eine binärdatei in den speicher lesen. soweit ich das verstehe, wird das so aber nicht funktionieren. habe ich recht, oder checke ich da einfach was fundemantal nicht?



  • Das wird so in der Tat nicht funktionieren. Gut gesehen.

    Die +=-Kiste ist übrigens nicht der einzige Bug in diesem Stück Code. Ich sehe auf den ersten Blick noch zwei weitere. Kannst du sie finden?



  • seldon schrieb:

    Das wird so in der Tat nicht funktionieren. Gut gesehen.

    danke! den code habe ich von jemandem, von dem ich mir nicht sicher war, ob er ein genie ist oder völlig verrückt. ich tendierte zwar von anfang an zu zweiterem, aber jetzt bin ich mir sicher. 😃

    seldon schrieb:

    Die +=-Kiste ist übrigens nicht der einzige Bug in diesem Stück Code. Ich sehe auf den ersten Blick noch zwei weitere. Kannst du sie finden?

    das einzige, was mir noch auffällt, ist, das man eine geöffnete datei auch wieder schließen sollte, aber das ist nicht wirklich ein bug im engeren sinne, denke ich. ansonsten weiss ich leider nicht, was du meinst. wie gesagt, meine C-kenntnisse sind schon etwas eingerostet. deshalb wäre ich zwecks auffrischung dankbar, wenn du mir die weiteren bugs aufzeigen könntest! 😉

    EDIT: was mir gerade noch aufgefallen wird: die variable i wird eigentlich nur wirklich in der einen auskommentierten zeile ganz am schluss verwendet, d.h. die könnte man eigentlich ganz wegkommentieren. aber auch das ist ja kein bug im engeren sinne, sondern einfach nur überflüssiger junk code (ganz so, wie es ihn auch in unserer DNA gibt 😉 )...



  • Das mit der Datei ist der eine, richtig. Das andere, was ich meinte, ist Folgendes:

    while(!feof(fp)){
            a = (char)fgetc(fp);
            ...
        }
    

    Der EOF-Status einer Datei wird erst gesetzt, nachdem eine Leseoperation am Ende der Datei fehlgeschlagen ist. Dementsprechend wird auf diese Weise nach dem letzten Zeichen der Datei noch einen Schleifendurchlauf weitergearbeitet und der Fehlercode, den fgetc zurückgibt, als Zeichen interpretiert.

    Richtiger wäre

    int c;
      while((c = fgetc(fp)) != EOF) {
        ...
      }
    

    EOF ist dabei ein negativer Integerwert (häufig -1) und somit außerhalb des Wertebereichs von unsigned char. Um diesen Mechanismus zu ermöglichen gibt fgetc auch int zurück und nicht char.

    In der Realität würde man natürlich mindestens blockweise einlesen, um sich das ständige Locking zu sparen; wenn man die Länge der Datei vorher feststellen kann, gerne auch alles auf einen Rutsch. fread ist hier dein Freund.



  • Weyl schrieb:

    also ist ein char auf den meisten üblichen computersystemen ein byte groß, oder?

    Andersherum.
    Ein Byte ist für den Compiler eine zusammenhängende Folge von Bits groß genug, zur Aufnahme jedes Zeichens aus dem Zeichensatz der aktuellen Ausführungsumgebung. Die Größe ist implementierungsabhängig (CHAR_BIT).
    D.h. also nicht, dass dein Betriebssystem in anderen Konstellationen nicht Umgebungen bereitstellen kann, in denen 1 Byte auch anders aussehen kann.



  • vielen dank für deine ausführliche erläuterung, seldon! 🙂

    Wutz schrieb:

    Weyl schrieb:

    also ist ein char auf den meisten üblichen computersystemen ein byte groß, oder?

    Andersherum.
    Ein Byte ist für den Compiler eine zusammenhängende Folge von Bits groß genug, zur Aufnahme jedes Zeichens aus dem Zeichensatz der aktuellen Ausführungsumgebung. Die Größe ist implementierungsabhängig (CHAR_BIT).
    D.h. also nicht, dass dein Betriebssystem in anderen Konstellationen nicht Umgebungen bereitstellen kann, in denen 1 Byte auch anders aussehen kann.

    ich bin mir nicht sicher, ob ich das ganz verstehe. kann man zumindest für PCs und MACs sagen, dass 1 char = 1 byte = 8 bit?



  • Das Compilersystem bzw. der C Standard kann keine Aussagen über Eigenschaften des Betriebssystems machen, nur welche über die ihm aktuell vom Betriebssystem zur Verfügung gestellten; oder kurz: im C Standard kommen Wörter wie PC, Mac, Unix, Windows und auch 16/32/64-Bit Umgebung nicht vor.



  • Weyl schrieb:

    ich bin mir nicht sicher, ob ich das ganz verstehe. kann man zumindest für PCs und MACs sagen, dass 1 char = 1 byte = 8 bit?

    Praktisch ja. Außerhalb des Embedded-Bereichs hat sich das so eingependelt, und es ist nicht abzusehen, dass sich das bald ändert. Eine Änderung der Bytebreite brächte arge Probleme in der Kommunikation mit anderen Maschinentypen mit sich, und sehr viel Code müsste neu geschrieben werden. Ich denke nicht, dass sich das für irgendjemanden lohnen könnte.

    Wenn du vorhast, in den Embedded-Bereich zu gehen, sieht es ganz anders aus. TI-Taschenrechner rechnen beispielsweise (soweit ich informiert bin) mit 16-Bit-Bytes, und mitunter fasst int da auch nicht mehr Werte als char. Dass an solche Szenarien nicht immer gedacht wurde, als die Funktionen, die später in die C-Standardbibliothek einziehen sollten, entworfen wurden, kann man am oben beschriebenen fgetc-Mechanismus wunderbar sehen; allerdings stellt sich die Frage eines Dateisystems in diesem Zusammenhang eh nicht. Generell kann man sich in diesem Bereich nicht darauf verlassen, dass einem der komplette C-Standard zur Verfügung steht oder alle Details ganz genau implementiert wurden.

    Oh, und wenn du ein historisches Interesse an alten Großrechnern hast, da geht es auch wild durcheinander. Zwischen 6 und 36 Bit pro Byte ist da fast alles zu haben.

    Gleichwohl: Wenn es sich mit vertretbarem Aufwand machen lässt, sollte man sich ruhig an CHAR_BIT ketten. Die Zukunft kann niemand vorhersehen, und wenn man sich eng an den Standard hält, hat man im Zweifel eine bessere Chance, dass der eigene Code die Änderung technischer Details unbeschadet überlebt. Pedanterie ist (in vernünftigen Grenzen) für Programmierer eine gute Angewohnheit.


Anmelden zum Antworten