Forum: Compiler & IDEs STM32, Bedeutung 1UL = unsigned long mit Wert 1 ?


von Matthias W. (Gast)


Lesenswert?

Hallo,

ich bin von den 8Bit Atmel auf den 32Bit STM32 (Keil Compiler) 
umgestiegen.
Ich finde in den Programmen immer wieder solche Sachen wie 1UL.

Was ich bisher schon herausgefunden habe ist, dass das UL wohl unsigned 
long bedeutet, aber der Wert davor, die Funktion der Zahl 1 ist mir 
nicht ganz klar. Heist das, dass die Zahl den Wert 1 hat, aber der Typ 
ein unsigned long ist?

Gruß Matthias

von Fabian O. (xfr)


Lesenswert?

Matthias W. schrieb:
> Heist das, dass die Zahl den Wert 1 hat, aber der Typ
> ein unsigned long ist?

Genau. Ohne Typangabe sind Konstanten vom Typ int. Das kann in manchen 
Rechenoperationen einen Unterschied machen.

Beispiel: Auf einem AVR ist ein int 16 Bit breit, ein long 32 Bit.

1         ist 0b0000000000000001
1 << 15   ist 0b1000000000000000
1 << 16   ist 0b0000000000000000
~1        ist 0b1111111111111110

1UL       ist 0b00000000000000000000000000000001
1UL << 15 ist 0b00000000000000001000000000000000
1UL << 16 ist 0b00000000000000010000000000000000
~1        ist 0b11111111111111111111111111111110

Wenn man also sicher gehen möchte, dass bei solchen Berechnungen die 
vollen 32 Bit genutzt werden, nimmt man 1UL. In der Praxis würde bei 
einem STM32 auch einfach 1 reichen, da ein int auf der Plattform 32 Bit 
breit ist. Es ist aber sauberer, wenn man darüber im Code keine Annahmen 
macht und explizit 1UL schreibt, wenn man 32 Bit braucht.

von (prx) A. K. (prx)


Lesenswert?

Fabian O. schrieb:
> Genau. Ohne Typangabe sind Konstanten vom Typ int.

Nur wenn sie da reinpassen. Wenn nicht, dann sind sie automatisch von 
einem entsprechen grösseren Typ.

von Fabian O. (xfr)


Lesenswert?

Stimmt, das hätte man noch erwähnen sollen.

Und es muss natürlich heißen:
~1UL      ist 0b11111111111111111111111111111110

von Rolf M. (rmagnus)


Lesenswert?

Fabian O. schrieb:
> In der Praxis würde bei
> einem STM32 auch einfach 1 reichen, da ein int auf der Plattform 32 Bit
> breit ist.

Aber er ist signed.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Fabian O. schrieb:

> Wenn man also sicher gehen möchte, dass bei solchen Berechnungen die
> vollen 32 Bit genutzt werden, nimmt man 1UL.

Wenn es wirklich 32 Bits braucht dann
1
#include <stdint.h>
2
3
UINT32_C(1)

Das geht dann auch, wenn ein long 64 bits lang ist oder nicht 
Standard-konform nur 16-bits, etwa avr-gcc -mint8

von W.S. (Gast)


Lesenswert?

Matthias W. schrieb:
> Ich finde in den Programmen immer wieder solche Sachen wie 1UL.

Nun, du hast schon das Richtige herausgefunden. Aber sowas wie 1UL ist 
eigentlich völlig überflüssiger Krempel. Kein heutiger Compiler braucht 
sowas - schon garnicht in der 32 Bit Welt. Das sind alles nur Altlasten 
aus den blutigen Anfängen von C.

Manchmal passiert es einem bei der Definition von Konstanten, daß man 
über Bit 30 hinausrutscht und dann meckert der Compiler, z.B. bei sowas:

#define PortA_Mode 3
#define PINSEL1  (PortA_Mode<<30) | (blablabla...)

In solchen Fällen schafft ein gezielter Typecast (unsigned long) das 
Problem aus der Welt.

W.S.

von (prx) A. K. (prx)


Lesenswert?

W.S. schrieb:
> In solchen Fällen schafft ein gezielter Typecast (unsigned long) das
> Problem aus der Welt.

Und was ist daran besser als die Notation 1UL?

Hältst du die Notation 1.0L-6 für ebenso überflüssig?

von S. K. (hauspapa)


Lesenswert?

> Notation 1.0L-6

Könnte mir das bitte jemand deuten?

besten Dank
Hauspapa

von (prx) A. K. (prx)


Lesenswert?

S. K. schrieb:
>> Notation 1.0L-6
>
> Könnte mir das bitte jemand deuten?

1.0E-6, aber als "long double" statt "double". Der Witz daran ist, dass 
kein Cast der Welt einmal verlorene Bits wieder hinzufügt. Eine 
Integerkonstante verliert keine Bits, weil der Compiler den Typ stets 
gross genug wählt. Bei Fliesskommakonstanten sieht das anders aus.

von W.S. (Gast)


Lesenswert?

A. K. schrieb:
> Hältst du die Notation 1.0L-6 für ebenso überflüssig?

Ja. Und es ist Pfusch.

W.S.

von Coder (Gast)


Lesenswert?

@W.S.

IHMO ist ein U bzw. UL ist kein überflüssiger Krempel, sowie typecasts 
sollten die Ausnahme bilden.

von (prx) A. K. (prx)


Lesenswert?

W.S. schrieb:
> Ja. Und es ist Pfusch.

Stimmt, weil 1.0E-6L korrekt ist.

Aber abgesehen davon: Wie würdest du 0.1 als "long double" Konstante 
ausdrücken? (long double)0.1 funktioniert nicht, denn
  0.1L - (long double)0.1
ist
  -0.00000000000000000555L
im 80-Bit-Format. Mir ist kein Weg bekannt, eine lexikalische Konstante 
für "long double" ohne Verlust an Genauigkeit anders anzugeben als mit 
"L" hinten dran.

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.