Forum: Compiler & IDEs define DATE "01.12.2015" trennen


von Peter (Gast)


Lesenswert?

Hallo,

ich möchte ein symbol, welches in der IDE (EW ARM) definiert ist 
trennen.
Speich ich habe ein
#define DATA "01.12.2015"
und möchte nun drei integer Werte mit Tag, Monat und Jahr daraus direkt 
definieren.

Klar könnte ich das ganze auch vom Controller umsetzen lassen und ich 
selbst würde auch lieber gleich den String verwenden doch leider habe 
ich die "A"-Karte bekommen und darf von einem alten Kollegen ein 
komplett vermurxtes Projekt übernehmen.

Peter

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

1
#define DATE "01.12.2015"
2
3
int getday(void) {
4
  return (DATE[0] - '0') * 10 + (DATE[1] - '0');
5
}
6
7
int getmonth(void) {
8
  return (DATE[3]  - '0') * 10 + (DATE[4] - '0') ;
9
}
10
11
int getyear(void) {
12
  return (DATE[6] - '0')  * 1000 +
13
    (DATE[7] - '0')  * 100 +
14
    (DATE[8] - '0')  * 10 +
15
    (DATE[9] - '0') ;
16
}

von PittyJ (Gast)


Lesenswert?

sollte auch mit sscanf gehen. In etwa so (nicht getestet):
sscanf(DATE,"%d.%d.%d",&day,&month,&year);

von Rolf M. (rmagnus)


Lesenswert?

PittyJ schrieb:
> sollte auch mit sscanf gehen.

Ob der Compiler das aber noch so optimiert kriegt, daß das komplett zur 
Compilezeit durchgeführt wird?

von JensM (Gast)


Lesenswert?


von Peter (Gast)


Lesenswert?

Hallo Jörg,

danke hat geklappt

Wusste gar nicht, dass der Preprozessor auf einzelne Zeichen eines 
defines zugreifen kann.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Peter schrieb:
> Wusste gar nicht, dass der Preprozessor auf einzelne Zeichen eines
> defines zugreifen kann.

Das ist nicht der Präprozessor. Wie kommst Du darauf?

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Peter schrieb:
> Wusste gar nicht, dass der Preprozessor auf einzelne Zeichen eines
> defines zugreifen kann.

Macht er auch nicht. Er ist nur ein Textersetzer.
1
  return (DATE[0] - '0') * 10 + (DATE[1] - '0');

Aufgelöst:
1
  return ("01.12.2015"[0] - '0') * 10 + ("01.12.2015"[1] - '0');

Gekürzt:
1
  return ('0' - '0') * 10 + ('1' - '0');

Terme ausgerechnet:
1
  return 1;

Das genau macht der Compiler.

Man hätte diese Funktionen übrigens auch als Makros schreiben können.

von Rolf Magnus (Gast)


Lesenswert?

Frank M. schrieb:
> Man hätte diese Funktionen übrigens auch als Makros schreiben können.

Zumindest sollte man sie static deklarieren, damit nicht unnötig eine 
non-inline-Version für den Aufruf von außen erzeugt wird.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

In C++ kann man es auch komplett in Konstanten packen:
1
#define DATE "01.12.2015"
2
3
const int day = (DATE[0] - '0') * 10 + (DATE[1] - '0');
4
const int month = (DATE[3]  - '0') * 10 + (DATE[4] - '0') ;
5
const int year = (DATE[6] - '0')  * 1000 +
6
    (DATE[7] - '0')  * 100 +
7
    (DATE[8] - '0')  * 10 +
8
    (DATE[9] - '0') ;

In C geht das aber nicht, das gibt ein “initializer element is not 
constant”.

von Walter T. (nicolas)


Lesenswert?

Frank M. schrieb:
> "01.12.2015"[0]

Sehr interessant. Ich wußte gar nicht, daß diese Schreibweise 
funktionieren kann.

von Chriss (Gast)


Lesenswert?

C-Buch :-)

von Peter II (Gast)


Lesenswert?

Walter T. schrieb:
>> "01.12.2015"[0]
>
> Sehr interessant. Ich wußte gar nicht, daß diese Schreibweise
> funktionieren kann.

du kannst sogar
1
0["01.12.2015"];

schreiben

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Jörg W. schrieb:
> In C++ kann man es auch komplett in Konstanten packen:

Hast du eine Erklärung, warum g++ 4.7 folgendes macht?
1
char c = "Hallo"[3];
1
.section  .text.startup,"ax",@progbits
2
  .type  _GLOBAL__sub_I_c, @function
3
_GLOBAL__sub_I_c:
4
  ldi r24,lo8(108)
5
  sts c,r24
6
  ret
7
8
  .size  _GLOBAL__sub_I_c, .-_GLOBAL__sub_I_c
9
  .global __do_global_ctors
10
.section .ctors,"a",@progbits
11
  .p2align  1
12
  .word  gs(_GLOBAL__sub_I_c)
13
.global  c
14
  .section .bss
15
  .type  c, @object
16
  .size  c, 1
17
c:
18
  .zero  1
19
  .ident  "GCC: (GNU) 4.7.2"

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Johann L. schrieb:
> Hast du eine Erklärung, warum g++ 4.7 folgendes macht?

Nö.  4.9 macht's nicht mehr:
1
        .file   "foo.C"
2
__SP_H__ = 0x3e
3
__SP_L__ = 0x3d
4
__SREG__ = 0x3f
5
__tmp_reg__ = 0
6
__zero_reg__ = 1
7
.global c
8
        .data
9
        .type   c, @object
10
        .size   c, 1
11
c:
12
        .byte   108
13
        .ident  "GCC: (GNU) 4.9.3"
14
.global __do_copy_data

von Rolf Magnus (Gast)


Lesenswert?

Walter T. schrieb:
> Frank M. schrieb:
>> "01.12.2015"[0]
>
> Sehr interessant. Ich wußte gar nicht, daß diese Schreibweise
> funktionieren kann.

Warum sollte sie nicht? "01.12.2015" ist vom Typ Array aus const char, 
und [0] ist die Schreibweise, um ans erste Element eines Arrays zu 
kommen. Kombiniere beides, und schon hast du das obige.
Es ginge z.B. auch:
1
const char* tmp = 3+"01.12.2015";
2
int monat = *tmp* 10+1 [tmp];

Zugegeben sehr unverständlich geschrieben. Hach, C kann so schön sein 
;-)

von Matthias H. (hallamen)


Lesenswert?

Johann L. schrieb:
> Hast du eine Erklärung, warum g++ 4.7 folgendes macht?

g++ 4.7 mit -std=c++11 optimiert den Ausdruck. Wenn man schon C++11 
verwendet, kann man auch const durch constexpr ersetzen, damit ist eine 
Auswertung zur comile-time garantiert.
1
#define DATE "01.12.2015"
2
3
constexpr int day = (DATE[0] - '0') * 10 + (DATE[1] - '0');
4
constexpr int month = (DATE[3]  - '0') * 10 + (DATE[4] - '0') ;
5
constexpr int year = (DATE[6] - '0')  * 1000 +
6
    (DATE[7] - '0')  * 100 +
7
    (DATE[8] - '0')  * 10 +
8
    (DATE[9] - '0') ;

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Matthias H. schrieb:
> g++ 4.7 mit -std=c++11 optimiert den Ausdruck.

Optimiert wurde er ja oben auch, nur eben dieses seltsame
_GLOBAL__sub_I_c generiert, welches vermutlich als statischer
Konstruktor den Initialwert setzen soll, statt das gleich dem
Assembler zu überlassen.

Kann sein, dass der Artefakt nur beim AVR-GCC auftritt.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Johann L. schrieb:
> Hast du eine Erklärung, warum g++ 4.7 folgendes macht?

Scheint übrigens eine reine GCC-4.7-Macke zu sein.  Ich habe hier auf
dem FreeBSD einen GCC 4.7 und einen 4.8 (Host-CC ist ja bei FreeBSD
inzwischen ohnehin Clang).

GCC 4.7:
1
        .file   "foo.C"
2
        .section        .text.startup,"ax",@progbits
3
        .type   _GLOBAL__sub_I_c, @function
4
_GLOBAL__sub_I_c:
5
.LFB1:
6
        .cfi_startproc
7
        movb    $108, c(%rip)
8
        ret
9
        .cfi_endproc
10
.LFE1:
11
        .size   _GLOBAL__sub_I_c, .-_GLOBAL__sub_I_c
12
        .section        .ctors,"aw",@progbits
13
        .align 8
14
        .quad   _GLOBAL__sub_I_c
15
        .globl  c
16
        .bss
17
        .type   c, @object
18
        .size   c, 1
19
c:
20
        .zero   1
21
        .ident  "GCC: (FreeBSD Ports Collection) 4.7.4"
22
        .section        .note.GNU-stack,"",@progbits

GCC 4.8:
1
        .file   "foo.C"
2
        .globl  c
3
        .data
4
        .type   c, @object
5
        .size   c, 1
6
c:
7
        .byte   108
8
        .ident  "GCC: (FreeBSD Ports Collection) 4.8.3"
9
        .section        .note.GNU-stack,"",@progbits

Was auch immer sie sich mit dieser Art Initialisierung gedacht haben.

von Peter (Gast)


Lesenswert?

Das hier generiert der IAR Compiler
1
        #define SHT_PROGBITS 0x1
2
3
        EXTERN printf
4
5
        PUBLIC Tag
6
        PUBLIC main
7
8
9
        SECTION `.rodata`:CONST:REORDER:NOROOT(2)
10
        DATA
11
        DC8 "%i"
12
        DC8 0
13
14
//    1 
15
//    2 
16
//    3 #define DATE "01.12.2015"
17
//    4 
18
19
        SECTION `.rodata`:CONST:REORDER:NOROOT(2)
20
        DATA
21
//    5 const int Tag = (DATE[0]-'0')*10 + (DATE[1]-'0');
22
Tag:
23
        DC32 1
24
//    6 
25
26
        SECTION `.text`:CODE:NOROOT(2)
27
        THUMB
28
//    7 int main()
29
//    8 {
30
main:
31
        PUSH     {R7,LR}
32
//    9   printf("%i", Tag);
33
        LDR      R0,??main_0
34
        LDR      R1,[R0, #+0]
35
        ADR      R0,??main_0+0x4  ;; 0x25, 0x69, 0x00, 0x00
36
        BL       printf
37
//   10   return 0;
38
        MOVS     R0,#+0
39
        POP      {R1,R3}
40
        BX       R3               ;; return
41
        Nop      
42
        DATA
43
??main_0:
44
        DC32     Tag
45
        DC8      0x25, 0x69, 0x00, 0x00
46
//   11 }
47
48
        SECTION `.iar_vfe_header`:DATA:NOALLOC:NOROOT(2)
49
        SECTION_TYPE SHT_PROGBITS, 0
50
        DATA
51
        DC32 0
52
53
        END

von Joachim B. (jar)


Angehängte Dateien:

Lesenswert?

Jörg W. schrieb:
> return (DATE[0] - '0') * 10 + (DATE[1] - '0');

geiler Code, die Einsparung war zwar nicht umwerfend, aber immerhin 158 
Byte!

im Prinzip wusste ich es noch, nur war ich unsicher ob das mit _DATE_ 
und "21.05.2015" klappt

nur _DATE_ hat eine Besonderheit, es gibt bei Tag keine führende NULL

deswegen:
(__DATE__[4]==' ') ? ta = __DATE__[5] - '0' : ta = (__DATE__[4] - '0') * 
10 + __DATE__[5] - '0';

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?


von Peter (Gast)


Lesenswert?

Mit dem _DATE_ wäre ich auch etwas vorsichtig bei unterschiedlichen 
compilern, bei dem von IAR kommt bei _DATE_ raus: "Dec  3 2015"

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Peter schrieb:
> bei dem von IAR kommt bei DATE raus: "Dec  3 2015"

Ernsthaft?

Der Standard sagt:
1
6.10.8.1 Mandatory macros
2
3
The following macro names shall be defined by the implementation:
4
5
__DATE__ The date of translation of the preprocessing translation
6
         unit: a character string literal of the form "Mmm dd yyyy",
7
         where the names of the months are the same as those generated
8
         by the asctime function, and the first character of dd is a
9
         space character if the value is less than 10. If the date of
10
         translation is not available, an implementation-defined valid
11
         date shall be supplied.

von Paul B. (paul_baumann)


Lesenswert?

Jörg W. schrieb:
> The following macro names shall be defined....

Soll defininiert werden...
Ist vielleicht aber nicht?

MfG Paul

Rolf Magnus schrieb:
> Hach, C kann so schön sein
> ;-)

Kann. Muß nicht.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Jörg W. schrieb:
> Peter schrieb:
>> bei dem von IAR kommt bei DATE raus: "Dec  3 2015"
>
> Ernsthaft?
>
> Der Standard sagt:
>
>
1
> 6.10.8.1 Mandatory macros
2
> 
3
> The following macro names shall be defined by the implementation:
4
> 
5
> __DATE__ The date of translation of the preprocessing translation
6
>          unit: a character string literal of the form "Mmm dd yyyy",
7
>          where the names of the months are the same as those generated
8
>          by the asctime function, and the first character of dd is a
9
>          space character if the value is less than 10. If the date of
10
>          translation is not available, an implementation-defined valid
11
>          date shall be supplied.
12
>

Ich sehe da keinen Widerspruch, sondern eher die Bestätigung, dass sich 
IAR daran hält.

Mmm  = "Dec"
dd   = " 3" (mit führendem Leerzeichen, wenn dd < 10)
yyyy = "2015"

Also: "Mmm dd yyyy" <=> "Dec  3 2015"

Passt doch. Oder habe ich da etwas missverstanden?

von Peter (Gast)


Lesenswert?

Ich würde auch sagen das das so korrekt ist.
zum Glück kann man bei iar die Variable aus der IDE $DATE$ in ein Symbol 
konvertieren und nutzen.
Da steht dann  03.12.2015 drin.

Die Variante von Jörg auf DeJa Vu ist etwas eleganter.

Peter

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Paul B. schrieb:
>> The following macro names shall be defined....
>
> Soll defininiert werden...

Paul, Englisch ist nicht so deine Stärke.  Standard-Kaudwerwelsch
erst recht nicht.

„shall“ in einem Standard ist eine bindende Verpflichtung.

Frank M. schrieb:
> Ich sehe da keinen Widerspruch, sondern eher die Bestätigung, dass sich
> IAR daran hält.

OK, oben hattest du zwischen „Dec“ und „3“ nur ein Leerzeichen.

Das mit dem führenden Leerzeichen (statt Vornull) ist ja in den weiter
oben beschriebenen Makros sauber abgefangen, d. h. diese Makros sind
portabel.  (Meine Variante hatte das nicht, aber der TE hatte ja
auch nicht _DATE_ geschrieben, sondern hatte die Vornull in seinem
DATE mit drin.)

Peter schrieb:
> zum Glück kann man bei iar die Variable aus der IDE $DATE$ in ein Symbol
> konvertieren und nutzen

Bei anderen Build-Systemen macht man das halt übers Makefile, sowas
war im oben verlinkten Thread ausgiebig diskutiert worden.

Die Variante, die rein mit dem C-Standard auskommt, hat aber natürlich
einen Bonus, da sie von keinerlei externem System abhängt.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Jörg W. schrieb:
> OK, oben hattest du zwischen „Dec“ und „3“ nur ein Leerzeichen.

Frank M. schrieb:
> Also: "Mmm dd yyyy" <=> "Dec  3 2015"
                              ^^

Nö, 2 :-)

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Frank M. schrieb:
> Nö, 2 :-)

Frank, ich meinte doch nicht dich, sondern einen „Peter“, der weiter
oben behauptet hatte, der IAR würde das anders machen:

Beitrag "Re: define DATE "01.12.2015" trennen"

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Jörg W. schrieb:
> Frank, ich meinte doch nicht dich,

Achso, dachte ich nur, weils unter meinem Zitat stand.

> sondern einen „Peter“, der weiter
> oben behauptet hatte, der IAR würde das anders machen:
>
> Beitrag "Re: define DATE "01.12.2015" trennen"

Da lese ich:

Peter schrieb:
> Mit dem DATE wäre ich auch etwas vorsichtig bei unterschiedlichen
> compilern, bei dem von IAR kommt bei DATE raus: "Dec  3 2015"
                                                      ^^

Auch 2 :-)

Aber egal, ich denke mal, der IAR machts richtig.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Angehängte Dateien:

Lesenswert?

Frank M. schrieb:
> Auch 2 :-)

Hmm, Mift.  Sorry.  Ich habe hier die Forums-Variante mit
Proportionalschrift, und selbst wenn man das dort mit der Maus
markiert (siehe Screenshot), sieht man nur ein Leerzeichen.
Nur in der Monospace-Schrift sieht man es richtig.

> Aber egal, ich denke mal, der IAR machts richtig.

Ja, auf jeden Fall.

Sorry für die Konfusion.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Jörg W. schrieb:

> Hmm, Mift.  Sorry.  Ich habe hier die Forums-Variante mit
> Proportionalschrift,

Sieht so aus, als ob diese Variante mehrfach hintereinander vorkommende 
Spaces zu einem Space "komprimiert". Sieht man auch an meinen beiden 
Pfeilen, die ich unter die Spaces positioniert hatte, um sie zu 
kennzeichnen. In Deinem Screenshot stehen sie ganz links am 
Zeilenanfang.

Hm, vielleicht ist das zu viel des Guten...

von Carsten S. (dg3ycs)


Lesenswert?

Hi,

ist zwar schon grob OFF TOPIC, aber da die Anfangsfrage ja schon 
vollstaendig zur Zufriedenheit beantwortet ist sollte das klar gehen:

Jörg W. schrieb:
> Paul B. schrieb:
>>> The following macro names shall be defined....
>>
>> Soll defininiert werden...
>
> Paul, Englisch ist nicht so deine Stärke.  Standard-Kaudwerwelsch
> erst recht nicht.

Doch, seine Uebersetzung ist schon OK, nur seine (und deine!) 
Interpretation des deutschen Textes laesst dann zu wuenschen uebrig!
>
> „shall“ in einem Standard ist eine bindende Verpflichtung.

Genau wie das deutsche soll - zumindest im juristischen Sinne.
ALso wenn das Wort in Gesetzen, Verordnungen, Urteilen, Richtlinien, 
aber auch Arbeitsanweisungen, Normen / Standards usw. auftaucht.
Da gilt immer: "Soll == Muss wenn kann/moeglich"

Damit gilt, wenn immer dort "soll" steht, MUSS das gemacht werden so 
lange es keine ernstzunehmenden Verhinderungsgruende gibt. Erst wenn es 
diese ernsthaften Hindernisse gibt kann auf die Ausfuehrung verzichtet 
werden.

Halt im Gegensatz zum "muss", wo bei ernsthaften Verhinderungsgruende 
diese Hindernisse ebend zwingend beseitigt werden muessen um das 
aufgegebene Umzusetzen.(das es dennoch Grenzen gibt muss ich ja wohl 
nicht extra erwaehnen)

Daher ist sein uebersetzter Text also durchaus vom Sinn her mit dem 
englischen identisch!

Gruss
Carsten

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Carsten S. schrieb:

> Daher ist sein uebersetzter Text also durchaus vom Sinn her mit dem
> englischen identisch!

Allerdings hatte er im nächsten Satz angezweifelt, ob es wirklich
wäre.  Das klingt eher wie das umgangssprachlich-deutsche „das sollst
du doch aber so tun!“

Als Referenz die Beschreibung aus dem C-Standard selbst:
1
In this International Standard, ``shall'' is to be interpreted as a requirement on an
2
implementation or on a program; conversely, ``shall not'' is to be interpreted as a
3
prohibition.

Ich finde das etwas stärker bindend als die im Deutschen übliche
Verwendung von „soll“, aber das ist Ansichtssache.  Wenn man sowas
in einem Gesetzestext findet, dann hat's vermutlich in der Tat die
gleiche Bindungskraft.

von Paul B. (paul_baumann)


Lesenswert?

Gut, dann sollte ich das anerkennen.
;-)

MfG Paul

von Konrad S. (maybee)


Lesenswert?

Viele Spezifikationen nutzen RFC 2119 "Key words for use in RFCs to 
Indicate Requirement Levels".
https://www.ietf.org/rfc/rfc2119.txt

von Carsten S. (dg3ycs)


Lesenswert?

Konrad S. schrieb:
> Viele Spezifikationen nutzen RFC 2119 "Key words for use in RFCs to
> Indicate Requirement Levels".
> https://www.ietf.org/rfc/rfc2119.txt

Ok,
dann bin doch ich der der falsch liegt...  ;-)

MUSS wäre dann die (sinngemäß) einzig 100% korrekte Übersetzung,
nicht bloß "muss wenn möglich%...

Gruß
Carsten

von Rolf M. (rmagnus)


Lesenswert?

"Muss" heißt für mich "geht gar nicht anders" (wir müssen alle 
irgendwann sterben). "Soll" dagegen heißt, dass man zwar eine Wahl hat, 
aber schlimme Dinge passieren, wenn man das "soll" nicht beachtet (du 
sollst nicht stehlen). "Sollte" ist dann eine demgegenüber stark 
abgeschwächte Variante (ich sollte mal wieder mein Auto waschen).

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Jörg W. schrieb:
> Host-CC ist ja bei FreeBSD inzwischen ohnehin Clang.

Ist der inzwischen so viel besser als GCC?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Johann L. schrieb:
> Jörg W. schrieb:
> Host-CC ist ja bei FreeBSD inzwischen ohnehin Clang.
>
> Ist der inzwischen so viel besser als GCC?

Was die genauen Beweggründe für diese Entscheidung waren, kann ich
dir jetzt nicht sagen.  Lässt sich sicher in einer Mailingliste
nachlesen.  Kann durchaus auch erstmal lizensmäßig von Interesse
sein (LLVM/Clang haben BSD-Lizenz, passen damit besser zu einem
BSD-Projekt als GCC).

Qualitätsmäßig fiel er zumindest dadurch auf, dass bei der Umstellung
auf Clang deutlich mehr an Warnungen kamen, die durchaus berechtigt
sind, d. h. Dinge, die der GCC nicht diagnostiziert hatte.  Auch sind
die Fehlermeldungen meiner Erinnerung nach detaillierter gewesen, da
hat GCC aber mittlerweile nachgezogen.

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
Noch kein Account? Hier anmelden.