Integer Konstanten

25/08/2011 - 09:13 von Heinz Saathoff | Report spam
Moin,

ich bin bei einem Compiler für Mikrocontroller auf einen Fehler
gestoßen, der sich anscheinend aus der unterschiedlichen Handhabung von
Konstanten und konstanten Ausdrücken ergibt. Für das Beispiel ist int
16 Bit und long mit 32 Bit groß.

// folgendes wird als Fehler betrachtet:
#define DAY_SECONDS (60*60*24)
unsigned long one_day = DAY_SECONDS;

Meldung des Compilers:
Integer arithmetic overflow, please typecast one constant
(to unsigned/larger)
(The default C type cast rules force significant bits in
the result to be cleared. A type cast can cure this)

// dies geht ohne Meldung durch:
#define DAY_SECONDS 86400
unsigned long one_day = DAY_SECONDS;

// dies aber auch
#define DAY_SECONDS ((unsigned long)60*60*24)
unsigned long one_day = DAY_SECONDS;


Ich nahm an, daß der Ausdruck 60*60*24 durch zur Compilezeit berechnet
wird und deshalb identisch zum vorberechneten Literal 86400 sei.

BTW, verlangt der Standard eigentlich, daß konstante Ausdrücke zur
Übersetzungszeit berechnet werden? Wenn nicht, wàre z. B.
int array[12*10];
oder
switch(i) {
case 13*2+4: ;
}
ungültig.



- Heinz
 

Lesen sie die antworten

#1 Marcel Müller
25/08/2011 - 11:30 | Warnen spam
Hallo!

Heinz Saathoff wrote:
// folgendes wird als Fehler betrachtet:
#define DAY_SECONDS (60*60*24)
unsigned long one_day = DAY_SECONDS;

Meldung des Compilers:
Integer arithmetic overflow, please typecast one constant
(to unsigned/larger)



Das ist (bei 16 Bit int) ein Überlauf. Hier wird nicht einfach ein
größerer Typ gewàhlt, nur weil es für das Multiplikationsergebnis
sinnvoll wàre.

// dies geht ohne Meldung durch:
#define DAY_SECONDS 86400
unsigned long one_day = DAY_SECONDS;



Müsste eigentlich
#define DAY_SECONDS 86400UL
heißen, oder? Wobei die meisten Compiler da nicht so pingelig sind.

// dies aber auch
#define DAY_SECONDS ((unsigned long)60*60*24)
unsigned long one_day = DAY_SECONDS;



Hier sehe ich kein Problem.

Ebenfalls OK wàre
#define DAY_SECONDS (60UL*60*24)


Ich nahm an, daß der Ausdruck 60*60*24 durch zur Compilezeit berechnet
wird und deshalb identisch zum vorberechneten Literal 86400 sei.



Die Annahme ist vernünftig. Eigentlich war 86400 schon problematisch.
Nur hat da der Compiler noch Gnade vor Recht walten lassen.
Kann auch sein, dass es eine Regel gibt, dass die Typangabe bei
offensichtlich für int zu großen Konstanten optional ist. Da bin ich mir
nicht ganz sicher. Ich würde es aber in so einem Fall nicht machen, da
es irreführend ist.

BTW, verlangt der Standard eigentlich, daß konstante Ausdrücke zur
Übersetzungszeit berechnet werden? Wenn nicht, wàre z. B.
int array[12*10];
oder
switch(i) {
case 13*2+4: ;
}
ungültig.



Das ist zulàssig.
Selbst das ist zulàssig:
int array[4*sizeof(int)];


Marcel

Ähnliche fragen