Beiträge von volatile_void

    bei der Zeile:

    Code
    Widget w = Widget(static_cast<char **>(&my_objects));

    ist meines Erachtens das & bei my_objects zuviel, sollte also:

    Code
    Widget w = Widget(static_cast<char **>(my_objects));

    heißen.

    Nur kurz überlegt:
    my_objects hat den Typ MyObject**, (&my_objects) hätte demnach den Typ MyObject***

    Ich weiß zwar nicht genau ob mit "Pointer auf ein Array von Objektpointern" das vllt eh genauso gemeint ist, wie du es im cast dann geschrieben hast, aber ein cast von MyObject*** auf char** scheint mir unlogisch.

    Hallo!

    Hätte da eine Idee für eine Variante die ohne Table-lookup auskommt. Ist aber noch nicht getestet (weder auf Korrektheit noch auf Performanz) und möglicherweise nicht ganz so schnell.

    Code
    unsigned char quersumme32(register unsigned int x) 
    {
        x = (x & 0x55555555) + ((x >> 1) & 0x55555555); /* 2bit sums */
        x = (x & 0x33333333) + ((x >> 2) & 0x33333333); /* 4bit sums */
        x = (x + (x >> 4)) & 0x0f0f0f0f;                /* byte sums */
        x = x + (x >> 8) + (x >> 16) + (x >> 24);
        return x & 0xff;
    }

    Meiner Ansicht nach müsste sich das in x86 Assembler superskalar in 12 Takten ausführen lassen, um zwar in etwa so:

    Zitat von Spockman

    Es gibt genuegend Garbage Collectoren fuer C/C++, und GC macht eine C++ Implementierung nicht non-conforming. GC ist ein C++-Implementierungsdetail, das vorhanden sein kann und oft auch vorhanden ist. Man kann das so daher nicht sagen - der ISO Standard schlieszt es jedenfalls nicht aus, und es gibt im Gegenteil immer wieder Bestrebungen, GC in den Standard zu nehmen. Es scheitert meist daran, dass die exakte Formulierung zu schwierig ist. De facto verwendet ohnehin jeder einen GC zumindest als Leak Detector.


    So jetzt muss ich auch mal meinen Senf zu C++ und Garbage Collection dazugeben:

    Die Tatsache, dass C++ keine Garbage Collection im Sprachstandard enthält ist meines Wissens auf folgende Umstände zurückzuführen:

    1. Bjarne Stroustrup ist (soweit ich mal irgendwo gelesen hab) der Meinung dass Speicherverwaltung nicht unbedingt in den Sprachstandard gehört. Es sei jedem freigestellt, die Speicherverwaltung zu verwenden, die er für richtig hält.

    2. Eine sichere allgemeine Garbage Collection ist in C++ nicht möglich, da der Programmierer vollen Zugriff auf die Zeiger hat. Es hindert ihn z.B nichts daran einen Zeiger in Form seines Einerkomplements abzuspeichern und so die Garbage Collection mit falschen Zeigerwerten zu täuschen und zur Freigabe eigentlich noch benötigten Speichers zu veranlassen.

    Prinzipiell stimm ich dir zu, dass Garbage Collection für C/C++ eine sinnvolle Erweiterung ist. Ich selbst habe aber noch nie eine GC bei C++ verwendet (zumindest wenn man Reference Counting nicht dazuzählt).
    Mir ist im Moment nicht ganz klar, wie derartige GCs funktionieren. Übernehmen die dann die gesamte Verwaltung des herkömmlichen Heaps oder laufen die parallel zu dem new/delete Allokationsschema auf einen separaten Heap, sodass herkömmlich allokierte Objekte und von der GC verwaltete Objekte gleichzeitg existieren können?

    Meiner Ansicht nach werden 2 String Instanzen erstellt:
    Eine Instanz wird in main() mittels String() erzeugt.
    Eine zweite Instanz wird erzeugt, da du diesen String per Kopie als Argument übergibst. Dabei sollte eigentlich der copy-Konstruktor aufgerufen werden, der für eine korrekte Kopie des Strings sorgen muss (der char array muss in der neuen Instanz neu angelegt werden, damit bei der Destruktion nicht derselbe Speicherbereich zweimal freigegeben wird). Somit wäre auch klar, dass der Destruktor zweimal gerufen werden muss.

    Allerdings ist es auch möglich, dass der Compiler die Instanz in main() wegoptimiert, da diese nur an setString() übergeben wird und ansonsten in main() nirgends verwendet wird. Damit würde dann auch die Benützung des copy-Konstruktors entfallen.

    Was allerdings da wirklich genau abläuft, und wieso der VC++ Compiler
    mal eine, mal zwei Instanzen erstellt, kann ich auch nicht genau sagen.

    struct c *create_config(float limit, short alarm_mode, short locked_mode){

    //
    struct c *poi;
    struct c config = {limit, alarm_mode, locked_mode};
    poi = (struct c *)malloc(sizeof(struct c));
    poi = &config; // falsch!
    // damit zeigt poi auf den Speicherbereich von config!
    // Dieser Speicherbereich wird ja am ende der funktion freigegeben!

    return poi;
    }

    richtig wäre z.B:

    struct c *create_config(float limit, short alarm_mode, short locked_mode){

    //
    struct c *poi;
    poi = (struct c *)malloc(sizeof(struct c));

    poi->limit = limit;
    poi->alarm_mode = alarm_mode;
    poi->locked_mode = locked_mode;

    return poi;
    }

    Zitat von sommeralex


    wie kann das sei?


    Wegen dem obengenannten Fehler überschreibt printf den Speicherbereich, auf den du mit p_config zeigst.

    Zitat von sommeralex


    ich dachte, wenn ich variabeln/structs während der laufzeit initialisiere, benötige ich malloc. dennoch liefert mein programm die richtige zahl, nämlich 3.


    Das ist hier nur zufällig so.
    Der Zeiger p_config zeigt auf die bereits freigegebene config struct am Stack. Da dieser Speicherbereich aber zwischenzeitlich noch nicht anders verwendet wurde, stehen dort noch die Werte, die du zugewiesen hast.
    Wenn du aber dazwischen noch einen Funktionsaufruf z.B von create_config(...) machst, stehendort wahrscheinlich vollkommen andere Werte.
    Probier mal folgendes:

    int main(){

    struct c *p_config = create_config(val_1, 2.3, 2, 3);

    (void) create_config(val_1, 4.0, 5, 6);

    short lm = p_config->locked_mode;
    printf("%d", lm);

    }

    Jetzt sollte was anderes herauskommen, weil der Speicherbereich mit anderen Werten überschrieben wurde.

    Zitat von sommeralex


    wenn ich in java auf ein objekt zeige, existiert es, solange ich darauf zeige.


    Jain. Genau genommen existiert es auch noch weiter, wenn du nicht mehr darauf zeigst. Erst wenn es dann von der Garbage Collection entfernt wurde, ist der Speicher endgültig freigegeben.

    Zitat von sommeralex


    wenn ich in C auf ein objekt zeige, und meinen zeiger de-referenziere, existiert das objekt weiter (obwohl ich nicht mehr darauf zugreifen kann) um es vom speicher zu entfernen, muss ich zuerst free() anwenden - stimmt das?


    Ja.

    Das Problem ist, dass der Compiler in main.c keine Kenntnis von dieser Struktur hat. Du solltest sie deshalb in einer Header-Datei definieren (z.B in extern.h).
    Das selbe solltest du auch für multipliziere machen, damit der Compiler die Argumentanzahl und -typen überprüfen kann.

    main.c

    Code
    #include <stdio.h>
     #include "extern.h"
    
    
    int main(){
      printf("Test");
      int ergebnis = mulitpliziere(3,4);
      return 0;
    }

    extern.h

    Code
    typedef struct{
      int x;
      double y;
      float z;
    }struktur;
     
     int multipliziere(int a, int b);

    extern.c

    Code
    int multipliziere(int a, int b){
      return a * b;
    }

    Ich hoff das funktioniert dann so (habs net ausprobiert).