Arrayinitialisierung nur per define möglich



  • Streiten würd ich das jetzt nicht nennen, wir sind ja friedlich und wollen am Ende nur mit bestem Wissen und Gewissen aus der Diskussion rausgehen. Ich hab' schonwieder ein bisschen dazu gelernt, und am Ende werde ich genau wissen, wann ich welche Konstante (bzw. Konstantendefinition) weswegen nehmen kann und nehmen sollte, darum gehts. 👍



  • dust schrieb:

    Bei #define SIZE 5 ersetzt der Preprozessor wie gesagt die entsprechenden Stellen (SIZE durch 5), die 5 taucht im Code der "EXE" und damit auch im Arbeitsspeicher (bei Ausführung) nicht auf. Das Array wird die Länge 5 haben und fertig. Andernfalls (nicht #define) ist die Länge ebenfalls klar, aber die 5 ist zusätzlich und völlig unnütz auch noch im Code und bei Ausführung im ProcessMemory oder wo auch immer vorhanden.

    Natürlich kommt die 5 irgend wo vor. Immerhin muss der Speicher ja nach bereit gestellt werden und dazu sollte man die Länge wissen.



  • Bei #define SIZE 5 ersetzt der Preprozessor wie gesagt die entsprechenden Stellen (SIZE durch 5), die 5 taucht im Code der "EXE" und damit auch im Arbeitsspeicher (bei Ausführung) nicht auf. Das Array wird die Länge 5 haben und fertig. Andernfalls (nicht #define) ist die Länge ebenfalls klar, aber die 5 ist zusätzlich und völlig unnütz auch noch im Code und bei Ausführung im ProcessMemory oder wo auch immer vorhanden.

    Natürlich kommt die 5 irgend wo vor. Immerhin muss der Speicher ja nach bereit gestellt werden und dazu sollte man die Länge wissen.

    Das hatten wir schon klar gestellt, dachte ich ..

    Aber einen Wert reinzupacken (auch, wenn es N mal ist) ist noch immernoch effizienter und weniger aufwändig, als jedesmal eine Adresse reinzupacken, die dann jedesmal angesprungen werden muss. Das meine ich, und ich denke jetzt versteht es auch jeder.

    Für mich ist jetzt nur noch unklar ob bei Konstanten, die durch const definiert wurden, bei Benutzung jener immer an die Adresse gesprungen wird, wo der Wert steht, oder ob, wie bei einer durch #define definierten Konstanten, überall der Wert der Konstante steht. Wenn immer die Adresse angesprungen werden würde, dann wär da für mich ganz klar ein Vorteil von #define.



  • dust schrieb:

    Für mich ist jetzt nur noch unklar ob bei Konstanten, die durch const definiert wurden, bei Benutzung jener immer an die Adresse gesprungen wird, wo der Wert steht, oder ob, wie bei einer durch #define definierten Konstanten, überall der Wert der Konstante steht. Wenn immer die Adresse angesprungen werden würde, dann wär da für mich ganz klar ein Vorteil von #define.

    möglicherweise kann ein compiler eine const-variable wegoptimieren, so dass das gleiche rauskommt, wie bei einem define.
    btw: verfechter von const-variablen pochen oft darauf, dass diese variablen eine typinformation haben, was ja bei einfachen defines nicht so ist (naja, nicht ganz, die sind, bei einfachen zahlen, vom typ 'int'). aber wenn man einen anderen typ als int braucht, kann man's mit define auch machen:

    #define CHARFOUR ((char)4)
    

    ein nachteil von const-variablen ist z.b. dass man das 'const' wegcasten kann:

    const int a = 0;
    *(int*)&a = 10;   // compiliert zwar, aber ob das gut ist?
    

    bei einem #define hat man mit solchen tricks keine chance

    #define TRULY_CONST 123
    TRULY_CONST = 10; // error
    *(int*)&TRULY_CONST = 10;   // error
    

    🙂



  • Nein, ein #define ist nichts anderes wie ein Text, dieser wird anstelle des
    Namens direkt in den Programmtext eingesetzt.

    #define HUHU das ist aber lustig

    schreibt Dir nun mal anstelle des HUHU den Text ins Programm.

    Man kann im Präprozessor auch prüfen, ob's das Ding gibt: #ifdef HUHU und #endif,
    dazu noch ein Paar andere Möglichkeiten. Es ist etwas völlig anderes wie eine
    Variablemdeklaration, es in eine Anweisung für den Präprozessor.



  • Scheppertreiber schrieb:

    Nein, ein #define ist nichts anderes wie ein Text, dieser wird anstelle des
    Namens direkt in den Programmtext eingesetzt.

    richtig! aber genau das ist machmal ein vorteil.
    🙂



  • fricky schrieb:

    Scheppertreiber schrieb:

    Nein, ein #define ist nichts anderes wie ein Text, dieser wird anstelle des
    Namens direkt in den Programmtext eingesetzt.

    richtig! aber genau das ist machmal ein vorteil.
    🙂

    Aber ja. Da soll der Compiler ja auch nichts optimieren.
    So ein #ifdef DEBUG ist äußerst praktisch ... 🙂



  • Scheppertreiber schrieb:

    fricky schrieb:

    Scheppertreiber schrieb:

    Nein, ein #define ist nichts anderes wie ein Text, dieser wird anstelle des
    Namens direkt in den Programmtext eingesetzt.

    richtig! aber genau das ist machmal ein vorteil.
    🙂

    Aber ja. Da soll der Compiler ja auch nichts optimieren.

    wie sollen ihn #defines am optimieren hindern?
    🙂



  • Der Compiler selbst dürfte ein #define nicht sehen. #define gehört nicht zum
    Sprachumfang, genau wie #include etc. Es sind Anweisungen für den Präprozessor.

    Was er nicht sieht kann er nicht optimieren.



  • Scheppertreiber schrieb:

    Der Compiler selbst dürfte ein #define nicht sehen...
    Was er nicht sieht kann er nicht optimieren.

    er sieht aber den quelltext, auf den #defines direkte auswirkungen haben.
    beispiel:

    #define HELLOTEXT "hello, world!"
    ...
    char *a = HELLOTEXT;
    char *b = HELLOTEXT;
    char *c = HELLOTEXT;
    

    der compiler kann 'string pooling' anwenden, damit der initialisierer nur einmal im binary vorkommt.
    🙂



  • Klar.

    Würde ich so etwas in einem PIC8 verwenden würde ich auch viel Wert drauf legen 🙂
    Für Windows ist das wurscht, da wird soviel mit Ressourcen geaast, da kommt's auf
    die Paar Bytes nicht an.

    In Deinem Beispiel würde ich das von Haus aus schon so definieren:

    char *p = "Hallo bin auch da";

    printf( "\n%s", p);
    printf( "\n%s", p);
    ...



  • Scheppertreiber schrieb:

    Würde ich so etwas in einem PIC8 verwenden würde ich auch viel Wert drauf legen 🙂
    Für Windows ist das wurscht, da wird soviel mit Ressourcen geaast, da kommt's auf
    die Paar Bytes nicht an.

    deswegen nimmt unter windows heute noch kaum jemand C. dafür gibt's ja .NET und ähnliches. aber da, wo C oft verwendet wird, ist auch sehr oft resourcensparendes programmieren angesagt.
    🙂



  • Es hat Gründe warum ich bei C bleibe:

    Ich habe eine wilde Mischung aus CGI- Kommandozeilen und Windowsprogrammen (da
    zum Glück aber nur wenige). Ich plane, das (wenn ich mal Zeit habe) auf Linux zu
    portieren. Versuche habe ich gemacht, geht relativ problemlos.

    NET etc. werde ich nicht verwenden. Ich bin dann auch wieder zu Updates gezwungen
    und das hänge ich mir nicht mehr ans Bein.

    C ist schnell, extrem flexibel und ich kann große System draus bauen. Der ++Overhead
    erinnert mich zu stark an Deutsche Verwaltung und bringt mir nichts.



  • Scheppertreiber schrieb:

    C ist schnell, extrem flexibel und ich kann große System draus bauen.

    da hast du recht, aber das bauen von grossen systemen ist in C verdammt aufwendig und fehleranfällig, bereits eine kleine windows-anwendung mit fensterchen oder dialogboxen und graphischen controls usw. würde ich nicht in C machen wollen (auch wenn's dafür libraries wie GTK u.ä. gibt).

    Scheppertreiber schrieb:

    Der ++Overhead erinnert mich zu stark an Deutsche Verwaltung und bringt mir nichts.

    meinst du C++? ja, das sind wir einer meinung. C++ finde ich auch total schrottig.
    🙂



  • Ok, fehleranfällig war C schon immer ...

    Beim Bauen größerer Systeme gibt es so ganz einfache Regeln:

    * keine Funktion größer wie der Bildschirm
    * Strukturen verwenden
    * immer wiederverwendbare Sachen in libs auslagern

    dann geht's.

    Ich mache nur recht wenige Win-Programme, die meisten sind HTML-Generatoren
    und Kommandozeilenprogramme. Wenn's um größere Datenmengen geht ist C nicht zu
    toppen.

    (Im Moment ein Archivsystem über's Web, die Windows-Programme sind standalone
    Dinger für die Kunden).



  • supertux schrieb:

    Tachyon schrieb:

    Gute Compiler sollten aber Defines auch dahin gehend auflösen können (glaube ich, bin mir nicht sicher).

    was soll das genau heißen? 😕

    Das soll heissen, dass es wohl Compiler gibt die es erkennen, wenn ein gleiches Literal an verschiedenen Stellen benutzt wird, und dieses Literal dann nur einmal in das Binary packen. Wird das Literal dann benutzt, wird es über eine Lookup-Tabelle herangezogen.

    Und ich weiss nicht, ich finde, man produziert mit Defines ziemlich schnell überflüssigen Overhead:

    #define SAMPLE_RATE 44100    //samplerate
    #define BLOCK_LENGTH_S 0.5f   //length of one block in s
    #define BLOCK_LENGTH ((int)(SAMPLE_RATE * BLOCK_LENGTH_S))
    #define BUFFER_SIZE (10 * BLOCK_LENGTH)
    
    /*...*/
    
    float buffer[BUFFER_SIZE]; /*-> float buffer[(10 * ((int)(44100 * 0.5f)))]*/
    
    /*...*/
    {
        int i;    
        for(i = 0; i < BLOCK_LENGTH; ++i) /*->for(i = 0; i < (10 * ((int)(44100 * 0.5f))); ++i) ::Yeah, defines are cool */
        {
            /*so something with buffer*/
            /*...*/
        }    
    }
    /*...*/
    while(expression)
    {
        if(counter < BUFFER_SIZE) /*-> if(counter < (10 * ((int)(44100 * 0.5f))): Great. Calculation in every cycle...*/
        {
            /*do something*/
        }
    }
    
    //Now C++:
    const unsigned int SAMPLE_RATE = 44100;
    const float BLOCK_LENGTH_S = 0.5f;
    const unsigned int BLOCK_LENGTH = SAMPLE_RATE * BLOCK_LENGTH_S; //evaluates to 22050
    const unsigned int BUFFER_SIZE = 10 * BLOCK_LENGTH; //evaluates to 220500
    
    float buffer[BUFFER_SIZE];
    
    /*...*/
    for(int i = 0; i < BUFFER_SIZE; ++i) //BUFFER_SIZE is 220500 no further calculations are necessary...
    {
    }
    

    Irgendwie finde ich defines doof... 🤡



  • Tachyon schrieb:

    //Now C++:
    

    diese zeile war ja mal sowas von überflüssig 😉



  • #define bzw. Makros sind recht praktisch, auch Sachen wie __DATE__, __TIME__,
    __FILE__ etc. Auch kann man mit #define den Code lesbarer machen (wen Du's nicht
    glaubst schau Dir ein Programm an was Du vor 5 Jahren verzapft hast :)).



  • Irgendwie finde ich die Diskussion über die Ablage von Integerliteralen sowieso reichlich merkwürdig.

    // nur ein Beispiel
    #define BLOCK_SIZE 44100 * sizeof(int)
    
    for (int i = 0; i < BLOCK_SIZE; ++i) {
    }
    

    Da wird der Compiler sowas draus machen:

    ...
    cmp [irgendwas], 176400
    ...
    

    Wo seht ihr (bzw. Tachyon) jetzt bitte das Potential, diese 176400 "nur einmal" ins Binary zu packen?



  • Tachyon schrieb:

    Und ich weiss nicht, ich finde, man produziert mit Defines ziemlich schnell überflüssigen Overhead:

    Welchen Overhead meinst du? Die falschen Kommentare werden vom Preprozessor entfernt, falls du das meinst...


Anmelden zum Antworten