Forum: Mikrocontroller und Digitale Elektronik negative variable in c programm


von anfänger (Gast)


Lesenswert?

Hallo,
möchte gerne in einem c programm eine variable mit einem negativen wert 
laden.

signed char variable;

void main ()
{

variable = -10;

}

geht das?

Danke.

von STK500-Besitzer (Gast)


Lesenswert?

Ja

von Εrnst B. (ernst)


Lesenswert?

Ja, schon. Wirft aber die Frage auf, warum du den Quelltext nicht 
einfach in einen C-Compiler geworfen hast... der wüsste die Antwort 
auch.

von mui (Gast)


Lesenswert?

ich dachte char ist immer unsigned?!

von Markus F. (pippo)


Lesenswert?

Man benutzt globale Variablen aber nur in Ausnahmefällen und wer so ne 
Frage stellt, wird kaum in so ner Situation sein ;) Also deklarier deine 
Variable lokal in main, sonst wird dir irgendwann mal jemand anständig 
auf die Finger haun

von ... (Gast)


Lesenswert?

nein

von ... (Gast)


Lesenswert?

Das "nein" bezog sich auf das vorhergehende. Also bei den Compilern kann 
man auch unsigned char für Strings erzwingen, aber normalerweise ist das 
ein 8-Bit Integer mit Vorzeichen.

von Sven P. (Gast)


Lesenswert?

char ist weder signed noch unsigned, sondern Umgebungsabhängig. Drum 
sollte man sich i.d.R. auch mal <stdint.h> anschauen.

von mui (Gast)


Lesenswert?

ah, alles klar, danke für die info.

von Bernd O. (bitshifter)


Lesenswert?

Sven P. schrieb:
> char ist weder signed noch unsigned, sondern Umgebungsabhängig.
Absolut richtig!

> Drum sollte man sich i.d.R. auch mal <stdint.h> anschauen.
Absolut falsch.

Wenn man char für etwas anderes als ASCII-Zeichen nutzen will, dann 
schaut man nicht in Header wie <stdint.h>, sondern verwendet die 
explizite Form "unsigned char" bzw. "signed char", dann läuft das 
Programm auch mit einem anderen Compiler nicht nur zufällig, sondern 
garantiert (jedenfalls dann wenn man nicht noch andere Compiler- und 
Plattformabhängigkeiten reinbaut ;-).

Der Blick in Headerdateien ist meist der Anfang eines Fehlers.


Gruß,
Bernd

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

>> Drum sollte man sich i.d.R. auch mal <stdint.h> anschauen.
> Absolut falsch.

Wieso?

> Wenn man char für etwas anderes als ASCII-Zeichen nutzen will, dann
> schaut man nicht in Header wie <stdint.h>, sondern verwendet die
> explizite Form "unsigned char" bzw. "signed char",

Was widerspricht Deiner Ansicht nach gegen uint8_t bzw. int8_t ?

von Karl H. (kbuchegg)


Lesenswert?

Bernd O. schrieb:

> Der Blick in Headerdateien ist meist der Anfang eines Fehlers.

LOL.
So krass würde ich das nicht ausdrücken, aber in diesem speziellen Fall 
hast du recht. Wenn es wichtig ist, ob char signed oder unsigned ist, 
benutzt man keinen plain vanilla char sondern ist immer explizit bzw. 
benutzt uint8_t bzw. int8_t.
Und zwar unabhängig davon ob char zufällig auf dem System schon die 
richtige Signedness hat. Damit erübrigt sich dann auch das Nachsehen im 
Headerfile.

von Stefan E. (sternst)


Lesenswert?

Bernd O. schrieb:

>> Drum sollte man sich i.d.R. auch mal <stdint.h> anschauen.
> Absolut falsch.

Was genau soll daran falsch sein?

> Wenn man char für etwas anderes als ASCII-Zeichen nutzen will, dann
> schaut man nicht in Header wie <stdint.h>, sondern verwendet die
> explizite Form "unsigned char" bzw. "signed char", dann läuft das
> Programm auch mit einem anderen Compiler nicht nur zufällig, sondern
> garantiert (jedenfalls dann wenn man nicht noch andere Compiler- und
> Plattformabhängigkeiten reinbaut ;-).
>
> Der Blick in Headerdateien ist meist der Anfang eines Fehlers.

Der Header stdint.h ist Bestandteil des C-Standards, und er ist genau 
dazu da, eben keine Compiler- und Plattformabhängigkeiten zu bekommen, 
wie es z.B. bei explizitem "signed/unsigned char" sein könnte (denn der 
Standard schreib keineswegs vor, wie groß ein char genau zu sein hat).

von (prx) A. K. (prx)


Lesenswert?

Bernd O. schrieb:

> Der Blick in Headerdateien ist meist der Anfang eines Fehlers.

Hast du stdint.h mit limits.h verwechselt?

von Sven P. (Gast)


Lesenswert?

Bernd O. schrieb:
>> Drum sollte man sich i.d.R. auch mal <stdint.h> anschauen.
> Absolut falsch.
>
> Wenn man char für etwas anderes als ASCII-Zeichen nutzen will, dann
> schaut man nicht in Header wie <stdint.h>, sondern verwendet die
> explizite Form "unsigned char" bzw. "signed char", dann läuft das
> Programm auch mit einem anderen Compiler nicht nur zufällig, sondern
> garantiert.

Na wenn du meinst. Welchen Wertebereich hat denn deiner Meinung nach ein 
'unsigned char' oder ein 'signed char'?

von Benedikt K. (benedikt)


Lesenswert?

Mal andersrum gefragt:
Was spricht gegen unsigend char, signed char?
Welche Vorteile bietet denn uint8_t und int8_t?

von Bernd O. (bitshifter)


Lesenswert?

Rufus t. Firefly schrieb:
>>> Drum sollte man sich i.d.R. auch mal <stdint.h> anschauen.
>> Absolut falsch.
>
> Wieso?
Wenn ein Programmieranfänger wissen möchte, wie groß char ist und ob 
char signed oder unsigned ist, dann läuft er Gefahr, anzunehmen, dass 
"char" unsigned ist und 8 bits hat.
Es ist leider so, dass sehr viele Programmierer glauben, dass char immer 
8 bit unsigned ist. Der Ursprung dieses Irrglaubens ist ziemlich klar: 
Entweder mal in den Headern nachgesehen oder empirisch ermittelt und als 
"gegeben" abgespeichert.

Darum:
Gerade als Anfänger nicht in Headern rumsuchen, sondern entweder im 
ANSI-C-Standard oder in den diversen C-Büchern/Tutorials nachschlagen.

Mein "absolut falsch" ist auf Anfänger bezogen. Natürlich spricht nichts 
dagegen, aus Neugier auch mal in den Headern zu stöbern - aber gerade 
Anfänger lernen viele falsche Dinge aus dem Studium von Headern.

Beispielsweise, dass Präprozessorvariablen mit zwei Unterstrichen 
beginnen sollen. Das geht eine ganze Weile lang gut und irgendwann hat 
man ein unerklärliches Programmverhalten, weil sich eine lokaler 
Bezeichner, der mit zwei Unterstrichen beginnt mit einem Bezeichner aus 
einer Library deckt.

Dito beim Schutz vor Mehrfachincludes durch "__MEINHEADER_H" findet sich 
leider oft - und wenn der Name des Headers generisch genug ist, dann 
beißt er sich mit dem System und die Fehlersuche geht los.

>> Wenn man char für etwas anderes als ASCII-Zeichen nutzen will, dann
>> schaut man nicht in Header wie <stdint.h>, sondern verwendet die
>> explizite Form "unsigned char" bzw. "signed char",
>
> Was widerspricht Deiner Ansicht nach gegen uint8_t bzw. int8_t ?

Kommt darauf an, was man damit vor hat. Um im Embedded-Bereich 
Arithmetik zu betreiben sind diese Typen gut geeignet. Wenn man aber 
intensiv mit der C standard library arbeitet sieht es wieder anders aus 
- oder wie ist der format-string zur ausgabe von uint8_t via printf() - 
also das Pendant zu "%d für int"?

Gruß,
Bernd

von Bernd O. (bitshifter)


Lesenswert?

Sven P. schrieb:
> Bernd O. schrieb:
>>> Drum sollte man sich i.d.R. auch mal <stdint.h> anschauen.
>> Absolut falsch.
>>
>> Wenn man char für etwas anderes als ASCII-Zeichen nutzen will, dann
>> schaut man nicht in Header wie <stdint.h>, sondern verwendet die
>> explizite Form "unsigned char" bzw. "signed char", dann läuft das
>> Programm auch mit einem anderen Compiler nicht nur zufällig, sondern
>> garantiert.
>
> Na wenn du meinst. Welchen Wertebereich hat denn deiner Meinung nach ein
> 'unsigned char' oder ein 'signed char'?
Mindestens 0 bis 255 bzw. mindestens -128 bis 127. Je nach Architektur 
auch mal mehr.

Gruß,
Bernd

von (prx) A. K. (prx)


Lesenswert?

Bernd O. schrieb:

> - oder wie ist der format-string zur ausgabe von uint8_t via printf() -
> also das Pendant zu "%d für int"?

Der ist wasserdicht definiert. Wenn du jedoch nach dem Formatstring zu 
int32_t gefragt hättest...

von Bernd O. (bitshifter)


Lesenswert?

Bernd O. schrieb:

> Mindestens 0 bis 255 bzw. mindestens -128 bis 127.
Korrektur:
-127 bit 127 für signed. Liegt an der unterschiedlichen Darstellung 
negativer Zahlen (explizites Bit für Vorzeichen vs. Zweierkomplement).

Gruß,
Bbernd

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

>> Was widerspricht Deiner Ansicht nach gegen uint8_t bzw. int8_t ?
>
> Kommt darauf an, was man damit vor hat. Um im Embedded-Bereich
> Arithmetik zu betreiben sind diese Typen gut geeignet. Wenn man aber
> intensiv mit der C standard library arbeitet sieht es wieder anders aus
> - oder wie ist der format-string zur ausgabe von uint8_t via printf() -
> also das Pendant zu "%d für int"?

Dafür sind Macros in /inttypes.h/ definiert.

http://www.opengroup.org/onlinepubs/000095399/basedefs/inttypes.h.html

von Sven P. (Gast)


Lesenswert?

Bernd O. schrieb:
> Bernd O. schrieb:
>
>> Mindestens 0 bis 255 bzw. mindestens -128 bis 127.
> Korrektur:
> -127 bit 127 für signed. Liegt an der unterschiedlichen Darstellung
> negativer Zahlen (explizites Bit für Vorzeichen vs. Zweierkomplement).
Na dann... Steht m.W.n. nirgendwo, dass ein char mindestens acht Bit 
haben muss. Er muss als unsigned lediglich den Basiszeichensatz 
aufnehmen können, dafür reichen z.B. auch 7 Bit.

Mit 'in den Header gucken' meinte ich auch eigentlich weniger, sich die 
Headerdatei reinzuziehen, sondern eher, mal in der Bibliothek 
nachzuschauen, was der Header so bietet.

Ansonsten ist auch der Formatstring für uint8_t wasserdicht definiert:
[c]
#include <stdint.h>
#include <inttypes.h>

printf("%" PRIu8, (uint8_t) 12);
[/pre]

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

> [c]
> :
> [/pre]
Das hat jetzt aber schnell gehen müssen, nicht wahr ;-)

von Sven P. (Gast)


Lesenswert?

Hoppla ;-)
Nönö, hat alle Zeit der Welt, muss eh warten, sons wär ich nich hier.

Ich wünschte, es gäbe mal einen 'Test-Übersetzer', der sich zwar 100% an 
den C-Standard hält, aber alles verquer hat:
- char mit 7 oder 9 Bit oder sowas
- Zeiger, die im Speicher als wirre Struktur liegen (und deshalb beim 
Casten nach Integer nicht mehr lineare Adressen ergeben)
- ...

von vlad (Gast)


Lesenswert?

wenn man rechnet, sollte man die typen uint8/16/32 benutzen.

wenn man strings will sollte man char* benutzen.

Warum?
weil je nach system die Breite eines Zeichen unterschiedlich sien 
könnte.
"hallo" ist dann zb pointer auf ein array von 16bit werten.
wenn dann char* text = "Hallo" steht gehts.
steht dann uint8* text= "Hallo" gehts nimmer.

gleiches gilt für die signedness von chars, wenn man wirklich 
zeichenketten will, einfach nur char, da ist das vorzeichen egal.
will man rechnen, dann nimmt man sowiso die stdint.h - typen

von Karl H. (kbuchegg)


Lesenswert?

Sven P. schrieb:
> Hoppla ;-)
> Nönö, hat alle Zeit der Welt, muss eh warten, sons wär ich nich hier.
>
> Ich wünschte, es gäbe mal einen 'Test-Übersetzer', der sich zwar 100% an
> den C-Standard hält, aber alles verquer hat:
> - char mit 7 oder 9 Bit oder sowas
> - Zeiger, die im Speicher als wirre Struktur liegen (und deshalb beim
> Casten nach Integer nicht mehr lineare Adressen ergeben)

Überhaupt: Pointertypen, die je nachdem worauf sie zeigen, 
unterschiedliche Länge haben.

von Rolf Magnus (Gast)


Lesenswert?

@Stefan Ernst:

> Der Header stdint.h ist Bestandteil des C-Standards,

Ja, aber erst seit 10 Jahren. Leider gibt es immer noch Compilerbauer, 
die es nicht mal gepackt haben, in dieser Zeit den Header mit 
aufzunehmen. Übrigens muß ein Compiler den eigentlich haben, wenn er von 
sich behauptete "ANSI"- oder "ISO"-C-konform zu sein, da es das vorher 
gültige C89 bzw. C90 nicht mehr gibt. Es wurde durch C99 ersetzt.

@Sven P.:

> Na dann... Steht m.W.n. nirgendwo, dass ein char mindestens acht Bit
> haben muss.

Das steht in ISO9899 tatsächlich nicht explizit drin. Was aber drin 
steht, sind die Minimalbereiche von -127 bis +127 bzw. 0 bis 255. Daraus 
ergibt sich dann implizit eine Größe von mindestens 8 Bit.

> Er muss als unsigned lediglich den Basiszeichensatz aufnehmen können,
> dafür reichen z.B. auch 7 Bit.

Das ist falsch.
1
#include <stdint.h>
2
#include <inttypes.h>
3
4
printf("%" PRIu8, (uint8_t) 12);

Der Cast wird dabei eigentlich nicht benötigt, da der Wert vor der 
Übergabe sowieso wieder nach int zurückkonvertiert wird. Das bedeutet 
auch, daß du für uint8_t gefahrlos %d nehmen kannst.

> Ich wünschte, es gäbe mal einen 'Test-Übersetzer', der sich zwar 100%
> an den C-Standard hält, aber alles verquer hat:

Dann brauchst du eine Deathstation 9000:
http://dspace.dial.pipex.com/town/green/gfd34/art/

> - Zeiger, die im Speicher als wirre Struktur liegen (und deshalb beim
> Casten nach Integer nicht mehr lineare Adressen ergeben)

Wie z.B. bei einem PC mit DOS?

von Rolf Magnus (Gast)


Lesenswert?

> wenn man rechnet, sollte man die typen uint8/16/32 benutzen.

Nein. Wenn man Typen braucht, die exakt eine bestimmte Größe haben 
müssen und weder kleiner noch größer sein dürfen, dann nimmt man diese 
Typen. Für die Code, wo man nur mindest-Anforderungen an die Größe hat, 
empfielt sich int_fast8_t bzw. int_least8_t u.s.w., da es je nach 
Prozessor z.B. nicht unbedingt einen exakt auf die gewünschte Breite 
passenden Typ geben muß oder dieser eigentlich nicht der optimale ist.

> wenn man strings will sollte man char* benutzen.

Ja.

> "hallo" ist dann zb pointer auf ein array von 16bit werten.
>
> wenn dann char* text = "Hallo" steht gehts.
> steht dann uint8* text= "Hallo" gehts nimmer.

Das stimmt, aber vermutlich aus einen anderen Grund, als du denkst. Denn 
wenn char 16 Bit breit ist, gibt es keinen uint8_t, da char per 
Definition immer der kleinste Typ ist.

von Sven P. (Gast)


Lesenswert?

Ich schrieb ja 'm.W.n.', hab mein Wissen aber nachgebessert :-)
In C99 steht tatsächlich explizit drin, dass ein char mindestens 8 Bit 
hat:

- Ein 'Objekt' sei in diesem Fall eine Variable eines Types.
- Das kleinste Objekt ist eine Variable des kleinsten Types der Sprache 
(kein Bitvektor).
- Das kleinste Objekt soll 8 Bit oder größer sein.

(Seite 21, §5.2.4.2.1)

von Simon K. (simon) Benutzerseite


Lesenswert?

Ich kann euch aus eigener Erfahrung sagen, dass dieses Thema nicht 
totzukriegen ist.

Selbst in der FH kriegen wir beigebracht, dass wir "char" benutzen 
sollen für 8 bit daten (zum beispiel port bitmasken).
Und sowas von einem Professor...

In der Schule war es damals auch schon so. Warum kennt niemand stdint.h? 
Warum legt eigentlich keine Lehrkraft mal Wert auf Ordentlichkeit und 
Sauberkeit und semantische Korrektheit auch bzgl. der Variablentypen? 
Das ist der (bzw. ein) Schlüssel zum Erfolg beim Programmieren, möchte 
ich behaupten...

von vlad (Gast)


Lesenswert?

das problem ist, dass der c99 standard nicht von allen compilern 
vollständig unterstützt wird (ist ja erst 10 Jahre alt ;).
VS 8 hat zB den header auch nicht.

>Für die Code, wo man nur mindest-Anforderungen an die Größe hat,
>empfielt sich int_fast8_t bzw. int_least8_t u.s.w., da es je nach
>Prozessor z.B. nicht unbedingt einen exakt auf die gewünschte Breite
>passenden Typ geben muß oder dieser eigentlich nicht der optimale ist.

Guter Tip danke, kannte ich auch noch nicht.
Das heißt auf einem 32bit DSP bekomme ich dann mit hoher 
wahrscheinlichkeit für int_fast8_t ein int32.

von Rolf Magnus (Gast)


Lesenswert?

> Das heißt auf einem 32bit DSP bekomme ich dann mit hoher
> wahrscheinlichkeit für int_fast8_t ein int32.

Wenn das in diesem Fall schneller ist und der Compiler sinnvoll 
implementiert ist, ja.

von vlad (Gast)


Lesenswert?

du meinst, wenn die standard-C-header sinnvoll implmementiert sind die 
int_fastx_t - Typen sind schließlich auch nix anderes als typedefs

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.