Forum: PC-Programmierung Konstanten Prefixe "U"und "UL"


von Thorsten R. (Gast)


Lesenswert?

Hallo,

ich schreibe grad für den AVR328 ein Programm und trotz guter C 
Kenntnisse bin ich etwas verwirrt, was die Fähigkeit des GCC angeht zu 
erkennen, wie lang Zahlen sind.

Der AVR ist 8 Bit, ich benutze uint8_t bis uint32_t Formate. Millies ist 
wohl ein uint32_t.

Für einen Timeout möchte ich so verfahren:

if (millis() > (to_timer + GSM_ONLINE_PERIOD)) {.....}

GSM_ONLINE_PERIOD sollen 90s, also 90.000 ms sein.
#define GSM_ONLINE_PERIOD (90*1000)

Muss dann hinter das 1000 dieses UL hinter? Steht wohl für unsigned 
long.
Ist beim AVR dann auch 32 Bit.

Also

#define GSM_ONLINE_PERIOD (90*1000UL)

Oder ist der GCC ist der Lage selbst zu erkennen in welches Format die 
defines passen?

Oder wäre es besser zu casten mit (uint32_t)(GSM_ONLINE_PERIOD )

Gruss,
Thorsten

von S. R. (svenska)


Lesenswert?

Thorsten R. schrieb:
> Oder ist der GCC ist der Lage selbst zu erkennen
> in welches Format die defines passen?

Die #defines sind pure Textersetzung vom Präprozessor, da gibt es keine 
Zahlen und Wertebereiche. Und für den Compiler ist alles "int" (was auf 
dem AVR nur 16 Bit breit ist), d.h. wann immer du aus "int" rausläufst, 
musst du einen größeren Datentyp erzwingen.

(long)(großer_ausdruck) läuft trotzdem über, weil (großer_ausdruck) 
überläuft. Da hilft dann auch eine nachträgliche Erweiterung nicht mehr.

Deswegen arbeitet man mit 1000UL.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Übrigens sind das keine Prefixe, sondern Suffixe.

Ein Prefix kommt davor, ein Suffix danach.

von Thorsten R. (Gast)


Lesenswert?

Hallo,

danke für Eure Antworten. Es wird klarer ;-)

Gruss,
Thorsten

von Rolf M. (rmagnus)


Lesenswert?

Thorsten R. schrieb:
> #define GSM_ONLINE_PERIOD (90*1000UL)
>
> Oder ist der GCC ist der Lage selbst zu erkennen in welches Format die
> defines passen?

In C gilt: Der Datentyp, mit dem eine Rechenoperation durchgeführt wird, 
hängt immer ausschließlich vom Typ der Operanden ab und nicht davon, 
wie groß das Ergebnis wäre oder wo es gespeichert wird. Bei der 
Multiplikation werden beide Operanden mindestens auf int erweitert, oder 
wenn einer größer ist, auf den größten Typ. Das ist auch unabhängig 
davon, ob die Berechnung zur Compilezeit oder zur Laufzeit durchgeführt 
wird.
Und dann gilt für die Konstanten: Alles, was in einen int passt, ist vom 
Typ int, wenn man nicht explizit was anderes vorgibt. Da sowohl 90, als 
auch 1000 vom Typ int sind, wird die Berechnung auch mit int 
durchgeführt. Da das Ergebnis auf einem AVR nicht in int passt, kommt 
dann Blödsinn raus. Der Suffix UL oben sagt, dass die 1000 vom Typ 
unsigned long sein soll. Das führt dazu, dass die 90 ebenfalls nach 
unsigned long vergrößert wird und die Berechnung dann damit ausgeführt 
wird. Das Ergebnis ist dann richtig, weil es in unsigned long (32 Bit) 
passt.

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.