Überlauf von character variable abfangen

Gast #2821773
Lesenswert?

Hallo,

und zwar stehe ich vor einem Problem in der Programmiersprache C, bis 
jetzt habe ich es noch nicht geschaft das Problem zu lösen, vieleicht 
schaft es ja ein C-Spezialist unter euch....
Folgendes Problem:

Es soll ein unsigned character und ein signed character addiert werden, 
dabei sollen wie die Namen schon sagen, dem unsigned der volle 
Wertebereich zur Verfügung stehen und dem unsigned von -127 bis 128. 
Jedoch sollen die Überläufe abgefangen werden d.h es darf nie kleiner 0 
und nie größer 255 werden.

Ich habe schon begonnen das Problem zu lösen und schaffe es auch das der 
Unterlauf abgefangen wird also die Variable wird nie kleiner 0, aber der 
Überlauf über 255 klappt nicht....vieleicht hat einer von euch eine 
bessere Idee.

hier mal Stück C-Code:
1
  if  ( (summensignal[2] < summensignal_offset[2]))
2
     stick_pitch =0;
3
  else 
4
     tick_pitch = summensignal[2] - summensignal_offset[2];
5
  
6
   motor1 = stick_pitch + stick_nick;

Dabei ist stick_pitch und motor1 unsigned, sowie stick_nick ist signed.

Hoffe ihr könnt etas mit der Frage anfangen und danke schon mal!!
Gast #2821792
Lesenswert?

> Jedoch sollen die Überläufe abgefangen werden d.h es darf nie
> kleiner 0 und nie größer 255 werden.

Das geht nicht.
C ist explizit so definiert, daß das Ergebnis in deinem Fall überrollt.
Wenn du in deiner Berechnung Überläufe abfangen willst, mußt du als 
temporären Zwischenwert einen entsprechend größeren Datentyp benutzen.

Überhaupt verstehe ich den Hintergrund nicht ganz.
'signed' und 'unsigned' sind quasi zwei verschiedene Interpretationen 
ein und derselben Speicherzelle. Das ist das gleiche wie Äpfel und 
Birnen addieren...
Gast #2821858
Lesenswert?

wieso sollten das Unterschiede sein? nur die Interpretation des 
Zahlenkreis ist anders z.b 27 in unsigned ist das gleich in signed aus 
Bitebene. Nur negative Zahlen sind etwas anders. Ich mache mal ein 
kleines Bsp dazu vieleicht wird es dann klarer wo es hin soll...

Mit positven Zahlen:
200 + 40 = 40

200 +  60 = 255

Mit negativen Zahlen:
100 + (-60) = 40

100 + (-120) = 0

Hintergrund ist: ein Motor soll ein Stellsignal in einem postiven 
Bereich von 0-255 von einer Fernsteuerung bekommen, das Signal wird aus 
2 Hebeln der Steurung gemischt eben aus Pitch und aus Nick das auch 
negativ werden kann.....

Danke den Tipp mit dem größen Zahlenbereich werde ich mal testen...
Gast #2821901
Lesenswert?

Simo schrieb:
> Ich mache mal ein
> kleines Bsp dazu vieleicht wird es dann klarer wo es hin soll...
>
> Mit positven Zahlen:
> 200 + 40 = 40
>
> 200 +  60 = 255
>
> Mit negativen Zahlen:
> 100 + (-60) = 40
>
> 100 + (-120) = 0

Bist Du sicher das dies auf allen Hardwareplatformen der Fall ist (zB 
auf  Mainframes* (ja, dafür gibt's auch C compiler))?

* IBM, UNISYS, SPERRY UNIVAC
#2821914
Lesenswert?

Norbert schrieb:
> Bist Du sicher das dies auf allen Hardwareplatformen der Fall ist

Hardwareseitige Saturierung ist eher für DSPs und MMX/SSE/... 
Befehlssätze typisch - ein Bereich, in dem sich Mainframes eher selten 
bewegen.

Wenn er das softwareseitig abfängt: Wo sollten Probleme auftauchen? Ok, 
signed char definiert nur -127..+127, aber das ist die einzige 
Einschränkung.
Gast #2821923
Lesenswert?

J.-u. G. schrieb:
> frame schrieb:
>> Das ist das gleiche wie Äpfel und
>> Birnen addieren...
>
> Du meinst, bei der Rechnung x = 100 + (-50) werden Apfel und Birne
> adddiert?

Nein. Die Werte sind beide vorzeichenbehaftet. Nur weil ein Wert positiv 
ist, macht ihn das ja nicht automatisch vorzeichenlos.
Gast #2821929
Lesenswert?

hervoragend :-) habe das Problem jetzt mit einer Tempvariablen mit 
größerem Wertebereich gelöst.
hier für alle die es interresiert....
1
temp_vari = (int16_t) (stick_pitch + stick_nick);
2

3
if (temp_vari > 255) temp_vari = 255;
4
if (temp_vari < 0) temp_vari = 0;
5
motor1 = temp_vari;

nachmals danke!!
#2821936
Lesenswert?

Nochmal:
In C gibt es eine Regel. Die besagt, dass Berechnungen grundsätzlich 
mindestens im kleinsten Datentyp 'int' ausgeführt werden. Es spielt 
schlicht und ergreifend keine Rolle ob du einen unsigned char mit einem 
signed char addierst. Denn als erstes werden beide Additionspartner 
sowieso zu einem int 'befördert', ehe dann die Addition ausgeführt wird.

Genau darum funktioniert deine Version. Denn das Ergebnis von

    stick_pitch + stick_nick

ist bereits ein int. Auch ohne Cast.
#2821940
Lesenswert?

PS: Wenn du mit dem Cast sicherstellen wolltest, dass auch ein schräg 
konfigurierter µC-Compiler das in 16 Bits rechnet - manche sind so 
einstellbar, dass standardwidrig aber effizienter keine Erweiterung 
auf int stattfindet - dann funktioniert das so nicht. Dann würde der es 
in 8 Bit Rechnung addieren und erst das falsche Ergebnis zu 16 Bits 
machen.

Dann geht das so:
   temp_vari = (int16_t)stick_pitch + (int16_t)stick_nick;
Gast #2821947
Lesenswert?

danke, das wusste ich garnicht, dass ehh alles in integer gerechnet 
wird. Ist das nicht Ressourcenverschwendung?

Habe bis jetzt immer in Assembler gerechnet da war immer("meistens" :-) 
) klar was an welcher Stelle passiert....
#2821953
Lesenswert?

Simo schrieb:
> danke, das wusste ich garnicht, dass ehh alles in integer gerechnet
> wird. Ist das nicht Ressourcenverschwendung?

Jain.
Es steht ja dem Optimizer frei, das Ganze wieder umzustossen, wenn er 
nachweisen kann, dass das Ergebnis dasselbe ist, wenn er anstelle einer 
16-Bit Berechnung auf 8 Bit runterkürzt.

>
> Habe bis jetzt immer in Assembler gerechnet da war immer("meistens" :-)
> ) klar was an welcher Stelle passiert....

AUch hier ist es klar, wenn man sein C gelernt hat.
Und genau aus dem Grund schreib ich mitlerweile unter jeden 3.ten Thread 
drunter: Kauf dir ein C-Buch! Da stehen solche Sachen (und noch 100-erte 
andere) nämlich drinnen.
Gast #2821962
Lesenswert?

also ich habe ein C-Buch, dass ist vieleicht nicht das Dickste und 
Beste, aber die Grundlagen stehen drin, allerdings besonders auf 
Berechnungen solcher Art werden nicht eingegangen!!! Welcher Buch kannst 
du denn empfehlen, in dem auch solch Dinge stehen @ Karl Heinz 
Buchegger?
#2821968
Lesenswert?

Simo schrieb:
> also ich habe ein C-Buch, dass ist vieleicht nicht das Dickste und
> Beste, aber die Grundlagen stehen drin, allerdings besonders auf
> Berechnungen solcher Art werden nicht eingegangen!!! Welcher Buch kannst
> du denn empfehlen, in dem auch solch Dinge stehen @ Karl Heinz
> Buchegger?

Wie immer den Klassiker

Kernighan & Ritchie
Programmieren in C


Wenn geht, die englische Original-Version. (keine Angst. das ist eine 
technische Doku und kein literarisches Meisterwerk. Mit Schulenglisch 
kommt man gut zurecht)
Persönliche Seite #2821974
Lesenswert?

A. K. schrieb:

> Wenn er das softwareseitig abfängt: Wo sollten Probleme auftauchen? Ok,
> signed char definiert nur -127..+127, aber das ist die einzige
> Einschränkung.

Wenn es C ist stlopert man gerne darüber daß signed-Overflow undefined 
ist:
1
int abs1 (int x)
2
{
3
    if (x < 0)
4
        x = -x;
5
        
6
    // Überlauf wegen -INT_MIN = INT_MIN = 0x800... ?
7
    return x < 0 ? INT_MAX : x;
8
    // Ebenso aussichtslos: (x & (1 << (8 * sizeof (int) -1)))
9
}
10

11
int abs2 (int x2)
12
{
13
    unsigned x = x2;
14
    
15
    if ((int) x < 0)
16
        x = -x;
17
        
18
    // Überlauf wegen -INT_MIN = INT_MIN = 0x800... ?
19
    return (int) x < 0 ? INT_MAX : x;
20
}
 
Einfach mal mit einem nicht allzu alten GCC compilieren.

Neben diesem händischen Saturieren gibt es auch die Embedded-C 
Erweiterung ISO/IEC TR 18037, die saturierte Arithnmetik implementiert. 
Einige Compiler wie avr-gcc unterstützen diese C-Erweiterung.
Gast #2823028
Lesenswert?

Hallo,

ich dachte immer, Berechnungen werden im größeren der beiden Datentypen 
durchgeführt, die an der Rechnung beteiligt sind?

Vor einiger Zeit hab ich mal einen uint16 mit einem Konstanten Wert von 
3000 multipliziert. Erst nachdem ich hier im Forum nachgefragt und einen 
Faktor nach uint32 gecastet habe hats geklappt. Auf einem AVR entspricht 
INT aber einem 32Bit Datentyp, also hätte doch der Cast nicht notwendig 
sein dürfen?

Kann mal schaun ob ich den Thread noch finde...

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