Forum: Mikrocontroller und Digitale Elektronik Wo ist der Fehler in diesem Programmcode?


von Tarek T. (tarek_t)


Lesenswert?

Hallo,

ich sitze bestimmt schon 60 Minuten an diesem Problem und bekomme es 
nicht gelöst. Vielleicht kann mir einer von euch helfen. Dazu erst 
einmal folgende Code-Zeilen:

Headerdatei:
1
typedef struct {
2
  ...
3
  unsigned int step_delay;
4
  ...
5
} speedRampData;
6
7
#define T1_FREQ 250000
8
#define SPR 200
9
#define ALPHA (2*3.14159/SPR)
10
#define T1_FREQ_148 (int)((T1_FREQ*0.676)/100)
11
#define A_SQ (long)(ALPHA*2*10000000000)

C-Code Datei:
1
speedRampData srd;
2
3
char buffer[10];
4
5
srd.step_delay = (T1_FREQ_148 * sqrt_Taylor(A_SQ / 100))/100;
6
7
uart_puts("step_delay: ");
8
itoa(srd.step_delay, buffer, 10);
9
uart_puts(buffer);

sqrt_Taylor() ist eine Funktion mit folgendem Prototypen:
1
unsigned long sqrt_Taylor(unsigned long x);

Diese gibt einfach die Wurzel der übergebenen Zahl zurück. In diesem 
Beispiel gibt sie 2507 zurück. Das habe ich auch mit Abfragen überprüft. 
Der Code ergibt so wenig Sinn, habe auch viel der Einfachheit halber mit 
Zahlen ersetzt, damit er besser verständlich ist.

Problem ist, so wie der Code oben steht, sendet er folgende Zeichen ans 
Terminal:
1
step_delay: -23168

Er soll aber:
1
step_delay: 42368

zurückgeben! Was auch passt, wenn es keinen Überlauf geben würde. Wieso 
kommt es zu dem Überlauf? Wieso kann der Compiler eine negative Zahl in 
einer als unsigned int deklarierten Variable abspeichern?

Ich komme da nicht drauf. Ich hoffe, mir kann jemand behilflich sein.

Vielen Dank im voraus

von Route_66 H. (route_66)


Lesenswert?

Hallo!
Der µC speichert alle Integer mit 16 Bit.
Wenn du ihn aber mit
>itoa(srd.step_delay, buffer, 10);
die 16 Bit als Integer behamndeln lässt, brauchst du dich über ein 
Vorzeichen nicht wundern.

von Karl H. (kbuchegg)


Lesenswert?

srd.step_delay  ist ein unsigned wert

itoa erwartet aber einen signed wert.

Um unsigned int zu wandeln, willst du die Funktion utoa benutzen.

i   wie integer       ... signed int       (itoa)
u   wie unsigned      ... unsigned int     (utoa)
l   wie long          ... signed long      (ltoa)
ul  wie unsigned long ... unsigned long    (ultoa)


Die Funktionen bilden eine Familie und es liegt an dir, die jeweils zum 
Datentyp passende zu wählen. Ansonsten wird einfach nur das Bitmuster 
hergenommen und passend zum Funktionsnamen ausgewertet. In deinem Fall 
dann eben als signed int.   Also mit Vorzeichen.


> Wieso kann der Compiler eine negative Zahl in einer als
> unsigned int deklarierten Variable abspeichern?

Letzen Endes sind es einfach nur 16 Bits, die abgespeichert werden. Und 
diese 16 Bit können sowohl eine unsigned Zahl (also ohne Vorzeichen), 
aber auch eine signed Zahl (also mit Vorzeichen) repräsentieren. Den 
Bits selber sieht man das aber nicht an, was sie sein sollen. Daher 
musst du die richtige Funktion benutzen. Mit der legst du fest, wie 
diese 16 Bit intepretiert werden sollen: signed oder unsigned.

von Tarek T. (tarek_t)


Lesenswert?

sauber, vielen Dank!

Man lernt nie aus ;-)

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.