32BIT unsigned int auf 16Bit uP?

Gast #1894607
Lesenswert?

Hallo

Kann mir jemand sagen wie ich eine 32Bit Variable definieren muss damit 
dies dann über den Compiler auf einem 16Bit uP läuft?
Ich arbeite mit dem PIC24FJ128 und dem Compiler MPC30.

Mit diesem Code bekomme ich 0x0000FFFF als Ausgabe, sollte aber 
0xFFFFFFFF sein...


long unsigned int test = 0xFFFFFFFF;
printf("test = %.8X \n\r", test);



Danke
Gast #1894655
Lesenswert?

Hallo Globi,

ich kenne Deinen Compiler nicht, aber beim GCC kann man mit den 
(Kommandozeilen) Parametern -Wall -Werror veranlassen, dass der Compiler 
ALLE Warnungen als Fehler behandelt und den Übersetzungsvorgang 
abbricht. Bei Deinem Problem hätte Dir dann der Compiler gesagt, dass 
das Format '%.8X' nicht zu dem Parameter 'test' passt.

Nur so als Hinweis ;-)

Beste Grüße

Alfred
Gast #1894664
Lesenswert?

Long-Konstanten sollte man übrigens auch besser mit angehängtem
L (signed long) bzw. UL (unsigned long) definieren.
also z.B.:
1
unsigned long test = 0xFFFFFFFFUL;

Viele Compiler werfen 'ne Warning "Constant is long" oder ähnlich, wenn 
man's nicht tut...

Gruß,
Thorsten
#1894735
Lesenswert?

Oleg schrieb:

> Ich kenne es auch vom AVR-GCC.

gcc auf 64-bit Linux sagt es in einem vergleichbaren Fall nicht.

> Warum ?

Portabilität.

Dadurch werden Daten und Rechnungen unnötig aufgeblasen. Wenn auf einer 
Maschine mit sizeof(long)=4 und sizeof(int)=2 alle Konstanten >int mit L 
oder UL versehen werden, dann kriegt man in einer Umgebung mit 
sizeof(long)=8 und sizeof(int)=4 unnötigerweise 64bit-Werte und 
Berechnungen. Und anschliessend wundert sich der sensibel eingestellte 
Compiler, dass er die in eine 32bit Variable schreiben soll (weil man 
uint32_t verwendet hat).

Letztlich müsste man dann konsequenterweise überall sowas grausliches 
hinschreiben wie:
  ((uint32_t)0xFFFFFFFFuL)

Im Kontext von Mikrocontroller ist das zwar noch nicht relevant, aber es 
gibt ja auch andere Umgebungen.
#1895508
Lesenswert?

Bei Angabe der Konstanten in Hex-Form fällt mir hier jetzt auf Anhieb 
auch kein problematischer Punkt ein.

Eine subtile Falle kann allerdings bei bestimmten dezimalen Konstanten 
lauern (Beispiel auf x86, also mit 32 Bit long):
1
#include <stdio.h>
2

3
long long i = -2147483648;
4

5
int main(void)
6
{
7
        printf("%lld\n", i);
8
        return 0;
9
}
1
% gcc -std=iso9899:1990 -g -O2 -W -Wall -o large large.c
2
large.c:3: warning: this decimal constant is unsigned only in ISO C90
3
% ./large
4
2147483648
5
% gcc -std=iso9899:1999 -g -O2 -W -Wall -o large large.c
6
% ./large
7
-2147483648

"long long" ist hier natürlich im C90-Fall eine GCC-Erweiterung, 
nichtsdestotrotz ist das Ergebnis "überraschend".

Der Hintergrund ist, dass es in ANSI-C eigentlich keine negativen 
Konstanten gibt. "-2147483648" ist die Konstante "2147483648", auf die 
dann eine Negation angewendet wird. In C90 ist "2147483648" nicht mehr 
in einem long darstellbar (soweit long 32 Bits hat), daher ist das dann 
ein unsigned long, und auch die Negation wird dann mit unsigned long 
gerechnet (so unsinnig das auch erstmal klingen mag), das Ergebnis 
bleibt positiv. In C99 wird dagegen auf long long (minimal 64 Bits) 
statt unsigned long zurückgegriffen, daher führt dann die Negation auch 
wirklich zu einem negativen Wert.

Andreas

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren