Arrayinitialisierung nur per define möglich



  • rüdiger schrieb:

    #include <stdio.h>
    
    enum { N = 10 };
    
    void foo() {
      printf("%d\n", N);
    }
    
    void bar() {
      enum { N = 100 };
      printf("%d\n", N);
    }
    
    int main() {
      enum { N = 2 };
      printf("%d\n", N);
      foo();
      bar();
    }
    

    Ich hoffe, dass dir das Problem nun einigermaßen klar geworden ist. (wenn nicht, ersetz mal das enum durch ein #define).

    #define N 10
    
    void foo() 
    {
      printf("%d\n", N);
    }
    
    void bar() 
    {
    #undef N
    #define N 100
      printf("%d\n", N);
    }
    
    int main() 
    {
    #undef N
    #define N 2
      printf("%d\n", N);
      foo();
      bar();
    }
    

    ja, und?
    wo ist da ein problem?



  • fricky schrieb:

    rüdiger schrieb:

    #include <stdio.h>
    
    enum { N = 10 };
    
    void foo() {
      printf("%d\n", N);
    }
    
    void bar() {
      enum { N = 100 };
      printf("%d\n", N);
    }
    
    int main() {
      enum { N = 2 };
      printf("%d\n", N);
      foo();
      bar();
    }
    

    Ich hoffe, dass dir das Problem nun einigermaßen klar geworden ist. (wenn nicht, ersetz mal das enum durch ein #define).

    #define N 10
    
    void foo() 
    {
      printf("%d\n", N);
    }
    
    void bar() 
    {
    #undef N
    #define N 100
      printf("%d\n", N);
    }
    
    int main() 
    {
    #undef N
    #define N 2
      printf("%d\n", N);
      foo();
      bar();
    }
    

    ja, und?
    wo ist da ein problem?

    Danke, du hast gut gezeigt, warum man define nicht nehmen sollte. So spart man sich solche umständlichen define/undef Orgien.

    Gut, dann ändern wir das Beispiel ein bisschen ab

    include <stdio.h>
    
    enum { N = 10 };
    
    void foo() {
      printf("%d\n", N);
    }
    
    void bar() {
      enum { N = 100 };
      printf("%d\n", N);
    }
    
    void baz();
    
    int main() {
      enum { N = 2 };
      printf("%d\n", N);
      foo();
      bar();
      baz();
    }
    
    void baz() {
      printf("%d\n", N);
    }
    

    Klar kannst du hier wieder ein undef/define machen. Aber dann musst du die gleiche Konstante an mehreren Orten verwalten und wofür das ganze, wenn du ein einfaches enum nehmen kannst?

    (btw. ich will nicht sagen, dass man define nie nie niemals benutzen darf. Ich benutze gerne define. Man muss sich nur bewußt sein, welche Nachteile das Sprachkonstrukt hat und hier hat es mehr Nachteile, als ein anderes Sprachkonstrukt (enum). Warum sich also damit rumquälen?)



  • rüdiger schrieb:

    (btw. ich will nicht sagen, dass man define nie nie niemals benutzen darf. Ich benutze gerne define. Man muss sich nur bewußt sein, welche Nachteile das Sprachkonstrukt hat und hier hat es mehr Nachteile, als ein anderes Sprachkonstrukt (enum).

    gegen enum hat ja auch keiner was (ich jedenfalls nicht).
    nur gegen:

    const int my_const = ...; // <-- das ist doof
    

    🙂



  • fricky schrieb:

    rüdiger schrieb:

    (btw. ich will nicht sagen, dass man define nie nie niemals benutzen darf. Ich benutze gerne define. Man muss sich nur bewußt sein, welche Nachteile das Sprachkonstrukt hat und hier hat es mehr Nachteile, als ein anderes Sprachkonstrukt (enum).

    gegen enum hat ja auch keiner was (ich jedenfalls nicht).
    nur gegen:

    const int my_const = ...; // <-- das ist doof
    

    🙂

    Warum denn? Oder trollst Du nur?



  • Nur fürs Protokoll

    static int const a = 5;
    
    int main() {
      int const b = 10;
      return a + b;
    }
    

    gcc-mp-4.3 -O3 -S foo.c
    ->

    .machine ppc
    	.text
    	.align 2
    	.globl _main
    _main:
    	li r3,15
    	blr
    	.subsections_via_symbols
    

    🙄

    Im übrigen sind defines auch beim debuggen nervig.



  • ; Listing generated by Microsoft (R) Optimizing Compiler Version 15.00.21022.08 
    
    	TITLE	C:\Users\Dennis\Desktop\test.c
    	.686P
    	.XMM
    	include listing.inc
    	.model	flat
    
    INCLUDELIB LIBCMT
    INCLUDELIB OLDNAMES
    
    CONST	SEGMENT
    _a	DD	05H <------ zumindest speicher verbraucht das const int
    CONST	ENDS
    PUBLIC	_main
    ; Function compile flags: /Ogtpy
    _TEXT	SEGMENT
    _main	PROC
    ; File c:\users\dennis\desktop\test.c
    ; Line 5
    	mov	eax, 15					; 0000000fH
    ; Line 6
    	ret	0
    _main	ENDP
    _TEXT	ENDS
    END
    


  • ^^ haste den code auch mal ganz ohne die 'const' ausprobiert. ich wette da kommt das gleiche raus.

    rüdiger schrieb:

    Im übrigen sind defines auch beim debuggen nervig.

    allerdings, da sind sie echt mies!
    🙂



  • fricky schrieb:

    ^^ haste den code auch mal ganz ohne die 'const' ausprobiert. ich wette da kommt das gleiche raus.

    rüdiger schrieb:

    Im übrigen sind defines auch beim debuggen nervig.

    allerdings, da sind sie echt mies!
    🙂

    Na dann erklär mal wie Sachen, die im zu kompilierenden Quelltext nicht auftauchen
    können das Debuggen beinflussen. Das ist wirklich hanebüchen.



  • fricky schrieb:

    ^^ haste den code auch mal ganz ohne die 'const' ausprobiert. ich wette da kommt das gleiche raus.

    Das ist anders, da ohne das const die sache veränderlich ist, und so theoretisch geändert werden kann(logisch, nicht?). Da die variable aber static ist und nirgends sonst genutzt wird, kann sie eigentlich entfernt werden, das wird sie aber wohl aus sicherheitsgründen nicht.

    Und dass die variable im speicher sein sollte ist auch klar sonst wäre ja &constVar unmöglich.



  • wurst schrieb:

    Und dass die variable im speicher sein sollte ist auch klar sonst wäre ja &constVar unmöglich.

    Der Compiler kann ja einfach entscheiden, ob er die Konstante in den Speicher packt, je nachdem ob man ihre Adresse anspricht oder nicht.



  • Scheppertreiber schrieb:

    fricky schrieb:

    ^^ haste den code auch mal ganz ohne die 'const' ausprobiert. ich wette da kommt das gleiche raus.

    rüdiger schrieb:

    Im übrigen sind defines auch beim debuggen nervig.

    allerdings, da sind sie echt mies!
    🙂

    Na dann erklär mal wie Sachen, die im zu kompilierenden Quelltext nicht auftauchen
    können das Debuggen beinflussen. Das ist wirklich hanebüchen.

    Denk doch bitte einmal nach, bevor du dich hier so aufführst. Es ist genau das Problem, dass es im Quelltext vorkommt, aber nicht beim "zu kompilierenden Quellcode". Für ein #define wird im Debugbuild kein Symbol angelegt, für ein enum oder ein const schon.

    @fricky
    Bei einem nicht const int kommt in diesem Fall natürlich das gleiche raus. Aber es ging ja um die Behauptung, dass bei einem const immer Speicher angelegt oder gar abgefragt werden muss. 🙂



  • Leider nicht überall 😮
    Und wenn ich jetzt auch bedenke das es ja wirklich _statisch_ ist(kompilation...) finde ich das auch verschwenderrisch.



  • Scheppertreiber schrieb:

    Na dann erklär mal wie Sachen, die im zu kompilierenden Quelltext nicht auftauchen
    können das Debuggen beinflussen. Das ist wirklich hanebüchen.

    wenn man durchs program steppt, sieht man bei enums das symbol, bei #defines nur den nackten zahlenwert. ganz furchtbar ist das debuggen, wenn man function-like macros hat. da geht fast gar nichts. d.h. macros, wenn sie als funktionsersatz dienen, müssen vorher gut getestet sein. genau so mit inline-funktionen. die sträuben sich auch oft gegen den debugger.

    wurst schrieb:

    Und dass die variable im speicher sein sollte ist auch klar sonst wäre ja &constVar unmöglich.

    kommt auf die verwendung an. so wie in rüdis code, wird überhaupt keine variable benötigt. also kann er sie komplett rausschmeissen.
    🙂



  • wurst schrieb:

    Leider nicht überall 😮
    Und wenn ich jetzt auch bedenke das es ja wirklich _statisch_ ist(kompilation...) finde ich das auch verschwenderrisch.

    das kann aber auch ein vorteil sein. wenn einem die platzierung wichtig ist, haben const-objekte schon ihre berechtigung:

    const char html[] = "<html><head>....</html>";  // 3 kB oder mehr
    ...
    // webserver auf einem microcontroller mit 8kB RAM und 256 kB FLASH
    if (request_received)
    {
       http_send (html, sizeof(html)-1);
    }
    ...
    

    ^^die webseite landet im read-only bereich (flash, ROM, ect), der viel grösser ist als der read-write memory (RAM).
    🙂



  • Aber hier ist ja das verhältnis zw. adressgröße und daten auch kleiner. Bei nem int oder einzelnem char-wert ist das meisten schlechter.



  • Er definiert die Stringlänge gleich 2mal, einmal durch SIZE und dann durch
    die Initialisierung des Strings. Es gibt nur recht wenige Spezialfälle wo so
    etwas Sinn machen könnte.

    ?

    #include <stdio.h>
    #include <string.h>
    
    int main() {
    	enum { SIZE=5 };
    	char array[SIZE] = "Test";
    	printf("1. %s\n", array);
    	strncpy(array, "Blah", SIZE-1);
    	printf("2. %s\n", array);
    	return 0;
    }
    

Anmelden zum Antworten