C-Programmiersprache, was bedeutet unsigned?

3 Antworten

Ob eine Zahl vorzeichenbehaftet ist, oder nicht, ist vor allem 'Interpretationssache' - Beim Zweierkomplement ändert sich an der grundlegenden Arithmetik nichts, deswegen nutzt man es so gerne.

Entsprechend gilt für Deinen Code, das Literal -3 wäre im 2er-Komplement:

1{n-2}01, mit Wortbreite n. Als vorzeichenlose Zahl entspricht das (2^n)-3.

Du legst also letztlich (2^n)-3 in a ab, printf jedoch interpretiert das dann wieder im 2er Komplement und erzeugt deswegen die Ausgabe -3.

Würde bei printf ein %u stehen, so würde (2^n)-3 ausgegeben. Bei 32-Bit Integern entsprechend:

4294967293

unsigned sorgt dafür, dass der Wert vorzeichenlos behandelt wird und der Wertebereich im positiven größer wird.

Das Gegenteil dazu wäre signed, was aber in C der default-Wert ist.

Ich habe jetzt gerade keinen C Compiler zur Hand, aber der Integer a wird durch das unsigned vorzeichenlos behandelt. Wenn du nun also schreiben würdest: printf("%d", a+3); müsste 6 und nicht 0 ausgegeben werden, da das Vorzeichen ignoriert wird.
Probier das doch mal aus und erzähl mir das Ergebnis!

Hier ist noch eine Seite, auf der das nochmal erklärt wird (mit einer schönen Tabelle für die Veränderung der Wertebereiche der einzelnen Datentypen): http://openbook.rheinwerk-verlag.de/c_von_a_bis_z/005_c_basisdatentypen_016.htm

Woher ich das weiß:Studium / Ausbildung

KleinGrau 
Beitragsersteller
 12.04.2020, 19:10

Hey! Danke für die Antwort. Tatsächlich kommt leider die 0 hierbei heraus.

LG

RainySky  12.04.2020, 20:04
@KleinGrau

Dann ist dein Compiler entsprechend schlau, um beim compilieren herauszufinden, dass du einen signed int in einen unsigned int schreiben willst und korrigiert es entsprechend.
Die Antwort von @Isendrak erzählt dir eigentlich alles notwendige ziemlich gut

Das ist relativ "einfach", wenn man das ganze nicht nur oberflächlich betrachtet:

Sowohl der signed-Wert -3 als auch der unsigned-Wert 4261412863 werden im Speicher als die Bytefolge fd ff ff ff abgelegt.

Jetzt beginnt der Spaß:

Du legst eine unsigned-Variable an und initialisierst diese mit einem signed-Literal. Offenbar kommt dein Compiler damit klar, indem er einen impliziten Typecast durchführt.

Dann verwendest du beim printf-Aufruf die Formatsequenz %d, die für signed-Werte vorgesehen ist. Noch ein impliziter Typecast, andernfalls würde der Compiler meckern.

Im Endeffekt ist der Unterschied zwischen signed und unsigned der Maschine vollkommen egal, beides ist auf "Maschinenebene" identisch.

P.S.: Falls du GCC verwendest, häng mal die Optionen -Wall -Wextra -Wpedantic -Werror mit an den Aufruf.


KarlRanseierIII  12.04.2020, 22:24

Die Optionen ändern nichts, es braucht schon ein -Wconversion und ein -Wformat-signedness, damit gcc murrt.

Isendrak  12.04.2020, 22:57
@KarlRanseierIII

Verdammt, tatsächlich. o.O

Dabei hätte ich ohne es auszuprobieren eigentlich damit gerechnet, dass spätestens -Wpedantic mindestens zu einem "Hey, bist du dir da wirklich sicher?" führt. ^^

KarlRanseierIII  12.04.2020, 23:05
@Isendrak

pedantic heißt ja nur: Alles was nicht strikt dem Standard folgt. Implizite Conversions sind aber Teil des Standards. Insofern, was soll er sich da schon groß aufregen :-D.

Isendrak  12.04.2020, 22:24
Noch als Nachtrag:

Die Bytesequenz fd ff ff ff gilt natürlich nur für Little-Endian-Systeme.

Bei einem Big-Endian-System wäre es ff ff ff fd.

Nachtrag Teil 2 (der unter anderem erklärt, warum -3 + 3 = 0 ist):

Wir haben einmal die -3 in der Form ff ff ff fd und die 3 in der Form 00 00 00 03.

Schritt für Schritt:

ff ff ff fd + 00 00 00 01 = ff ff ff fe
ff ff ff fe + 00 00 00 01 = ff ff ff ff
ff ff ff ff + 00 00 00 01 = 00 00 00 00