Unterschied zwischen vorzeichenlosem und vorzeichenbehaftetem int-Zeiger

Lesezeit: 2 Minuten

Gibt es sowas wie ein unsigned int* was anders ist als int*. ich weiß das unsigned hat einen höheren Wertebereich. Kann es trotzdem nicht int* sogar auf irgendwelche hinweisen unsigned int?

  • Ein Zeiger zeigt auf Bits. Der Typ des Zeigers informiert Sie darüber, auf wie viele Bits verwiesen wird und was sie “bedeuten”. Ohne diese Informationen sind die Bits bedeutungslos.

    – Heiße Licks

    23. Dezember 2014 um 17:41 Uhr

  • @HotLicks: Ein Zeiger zeigt auf ein Objekt eines bestimmten Typs.

    – Keith Thompson

    23. Dezember 2014 um 17:52 Uhr

  • @KeithThompson – Ein Zeiger gibt den Typ an. Vielleicht auf die richtige Weise, vielleicht auch nicht.

    – Heiße Licks

    23. Dezember 2014 um 18:00 Uhr

  • Der “Typ” eines Zeigers teilt dem Compiler mit, welche Art von Daten an dieser Adresse zu erwarten sind, wenn Sie ihn dereferenzieren oder Zeigerberechnungen durchführen. Aber es ist wirklich nichts weiter als eine Adresse. Schließlich kann es sonst nicht wissen, was zufällige Bits an einer zufälligen Adresse bedeuten, es sei denn, Sie sagen es ihm.

    – Lee Daniel Crocker

    23. Dezember 2014 um 18:07 Uhr

  • Interessant zu sehen, dass es 3 Antworten gibt, die höher bewertet sind als die akzeptierte. Wäre interessant, die Gedanken von OP zur Auswahl zu erfahren.

    – chux – Wiedereinsetzung von Monica

    24. Dezember 2014 um 15:59 Uhr

Benutzer-Avatar
ouah

int * und unsigned int * sind zwei verschiedene Zeigertypen, die nicht kompatible Typen sind. Sie sind auch Zeiger auf inkompatible Typen. Zur Definition von kompatible Typenbitte beziehen Sie sich auf § 6.2.7 im C-Standard (C11).

Zeiger auf inkompatible Typen zu sein, bedeutet beispielsweise Folgendes:

unsigned int a = 42;

int *p = &a;  // &a is of type unsigned int *

ist nicht gültig (die Einschränkungen des Zuweisungsoperators werden verletzt).

Ein weiterer Unterschied zwischen den beiden Typen besteht darin, dass es für die meisten anderen Zeigertypen (obwohl hier unwahrscheinlich) keine Garantie von C gibt, dass sie die gleiche Größe oder die gleiche Darstellung haben.

  • Umwerben. Die Frage lautet: “Gibt es etwas wie ein unsigned int*, das sich von int* unterscheidet”, sagen Downvoter bitte, was in meiner Antwort falsch ist.

    – au

    23. Dezember 2014 um 18:03 Uhr


  • Ich sehe nichts Falsches in dieser Antwort. Wenn Sie sich nicht trauen, einen Kommentar abzugeben, stimmen Sie bitte nicht ab.

    – Hacken

    23. Dezember 2014 um 18:05 Uhr


  • @Namfuak es ist aus C-Sicht ungültig. Die Einschränkungen des Zuweisungsoperators werden verletzt. Eine Diagnose ist erforderlich und ein Compiler kann sich weigern, das Programm zu übersetzen.

    – au

    23. Dezember 2014 um 21:23 Uhr

  • Dieser Code ist jedoch eine Beschränkungsverletzung int *p = (int *)&a ist gültig. Ihre Antwort befasst sich nur damit, ob für die Kompilierung eine Besetzung erforderlich ist, während OP anscheinend gefragt hat, was zur Laufzeit passiert, wenn die Besetzung enthalten ist.

    – MM

    23. Dezember 2014 um 23:41 Uhr


  • @MattMcNabb Das widerspricht direkt dem eigenen Rat von SE. Das Heruntervoten eines Kommentars mit <2k Wiederholung gibt die Nachricht “Bitte erwägen Sie, einen Kommentar hinzuzufügen, wenn Sie der Meinung sind, dass dieser Beitrag verbessert werden kann.”

    Benutzer820304

    24. Dezember 2014 um 0:41 Uhr


Benutzer-Avatar
2501

Die Verwendung eines vorzeichenlosen Zeigers, um auf eine vorzeichenbehaftete Version des gleichen Typs zu zeigen, wird von C Standard definiert.

Daher ist die Interpretation eines int durch einen vorzeichenlosen int-Zeiger und umgekehrt gültig.

ISO/IEC 9899:201x 6.5 Ausdrücke, S. 7:

Auf den gespeicherten Wert eines Objekts darf nur durch einen lvalue-Ausdruck zugegriffen werden, der einen der folgenden Typen hat: 88)

— ein Typ, der der Typ mit oder ohne Vorzeichen ist, der dem effektiven Typ des Objekts entspricht,

— ein Typ, der der Typ mit oder ohne Vorzeichen ist, der einer qualifizierten Version des effektiven Typs des Objekts entspricht,

88) Die Absicht dieser Liste besteht darin, die Umstände anzugeben, unter denen ein Objekt mit einem Alias ​​versehen werden kann oder nicht.

Der effektive Typ ist im Grunde der Typ des Objekts:

Der effektive Typ eines Objekts für einen Zugriff auf seinen gespeicherten Wert ist der deklarierte Typ des Objekts, falls vorhanden.

Es wurde ein Problem bezüglich der Auslegung der obigen Regel aufgeworfen. Das Folgende ist meine zusätzliche Begründung dazu.

Dieser Text unten ist nur für die semantische Argumentation des Wortes aufgeführt: entsprechende , und nicht für die direkten Regeln, die es spezifiziert.

6.2.5 Typen

p6: Für jeden der vorzeichenbehafteten Integer-Typen gibt es a dazugehörigen (aber unterschiedlicher) vorzeichenloser Integertyp (mit dem Schlüsselwort unsigned bezeichnet), der dieselbe Speichermenge (einschließlich Vorzeicheninformationen) verwendet und dieselben Ausrichtungsanforderungen hat.

p9: Der Bereich nicht negativer Werte eines vorzeichenbehafteten ganzzahligen Typs ist ein Unterbereich von
dazugehörigen ganzzahliger Typ ohne Vorzeichen, und die Darstellung des gleichen Werts in jedem Typ ist gleich.41)

p12: Für jeden schwebenden Typ gibt es a dazugehörigen echter Typ, der immer ein echter Floating-Typ ist. Bei echten Floating-Typen handelt es sich um denselben Typ. Bei komplexen Typen ist dies der Typ, der durch Löschen des Schlüsselworts _Complex aus dem Typnamen angegeben wird.

p27: Außerdem gibt es den _Atomic Qualifier. Das Vorhandensein des Qualifizierers _Atomic bezeichnet einen atomaren Typ. Die Größe, Darstellung und Ausrichtung eines atomaren Typs muss nicht die gleiche sein wie die des dazugehörigen unqualifizierter Typ

6.2.6.2 Integer-Typen

p2: Für vorzeichenbehaftete Integer-Typen müssen die Bits der Objektdarstellung in drei Gruppen unterteilt werden: Wertbits, Füllbits und das Vorzeichenbit. Es müssen keine Füllbits vorhanden sein; signed char darf keine Füllbits haben. Es soll genau ein Vorzeichenbit geben. Jedes Bit, das ein Wertbit ist, muss den gleichen Wert haben wie das gleiche Bit in der Objektdarstellung des dazugehörigen vorzeichenloser Typ

p5: Die Werte aller Füllbits sind nicht spezifiziert. 54) Eine gültige (Nicht-Trap-) Objektdarstellung eines vorzeichenbehafteten ganzzahligen Typs, bei der das Vorzeichenbit Null ist, ist eine gültige Objektdarstellung des entsprechenden vorzeichenlosen Typs und muss denselben Wert darstellen .

(Und viele weitere Beispiele mit identischer Verwendung des Wortes “korrespondierend”)

Wie Sie in den obigen Ausschnitten sehen können, verwendet Standard das Wort “entsprechend”, um sich auf verschiedene Typen oder Typen mit unterschiedlichen Bezeichnern und/oder Qualifizierern zu beziehen. Wie in den obigen Beispielen zu sehen ist, verwendet Standard daher das Wort so, wie es in diesem Beispiel verwendet würde: qualifizierter Typ entspricht Typ.

Es wäre unlogisch, das Wort “entsprechend” plötzlich für einen anderen Zweck zu verwenden: sich auf völlig identisch qualifizierte/spezifizierte Typen zu beziehen und die Dinge sogar noch mehr zu verwirren, indem die Wörter “signed” und “unsigned” ohne triftigen Grund in denselben Satz aufgenommen werden.

Die Absicht von 6.5, p7 ist: a type that is the signed or unsigned type entweder ein vorzeichenbehafteter oder ein vorzeichenloser Typ corresponding to the effective type of the object die andernfalls mit dem Zieltyp übereinstimmt (entspricht). Also zum Beispiel: effektiver Typ ist: int, int oder unsigned int entsprechen diesem Typ.

  • Du meinst das int * und unsigned int * austauschbar ohne Besetzung ?

    – Gamal Othman

    11. März 2019 um 11:00 Uhr

Benutzer-Avatar
MM

unsigned int * und int * sind verschiedene Arten. Um das eine in das andere umzuwandeln, müssen Sie einen Cast verwenden.

Wenn Sie einen Wert über einen Zeiger lesen, versucht er, die an dieser Speicherstelle gespeicherten Bits so zu interpretieren, als wären sie Bits für den Typ, auf den der Zeiger zeigt, auf den Sie lesen.

Wenn die Bits an dieser Speicherstelle nicht von einem Zeiger desselben Typs geschrieben wurden, den Sie durchlesen, wird dies aufgerufen Aliasing.

Die strenge Aliasing-Regel gibt an, welche Typen Aliasings haben dürfen oder nicht; alasing zwischen einem Typ signed und unsigned Versionen ist immer erlaubt.

Wenn die Bits jedoch keine gültige Darstellung eines Werts in dem Typ sind, den Sie lesen, führt dies zu undefiniertem Verhalten.

Auf modernen Systemen gibt es keine solchen “Fallen” -Darstellungen, sodass Sie kein Problem haben. Aber nehmen wir an, Sie befanden sich in einem 1er-Komplementsystem, das auf einer negativen Null gefangen ist:

unsigned int x = 0xFFFFFFFF;
int *y = (int *)&x;
printf("%d\n", y);

Der Leseversuch y kann einen Hardwarefehler oder ein anderes Verhalten verursachen.

  • Also anscheinend gcc und clang erlauben diese Zuweisung ohne Besetzung als Erweiterung obwohl ich Ich kann nicht sagen, dass die Argumentation hinter der Erweiterung gut ist

    – Shafik Yaghmour

    29. Januar 2018 um 5:57 Uhr

  • @ShafikYaghmour Sie drucken eine Diagnose, damit sie dem Standard entsprechen; Der Knackpunkt ist, dass die Diagnose standardmäßig auf “Warnung” und nicht auf “Fehler” lautet.

    – MM

    29. Januar 2018 um 8:27 Uhr

  • Ich gebe zu, dass ich die Vorteile von Compiler-Erweiterungen nutzen kann char *, unsigned char * austauschbar ist es ärgerlich, wenn mit Puffern aus gemischten binären Daten und Text gearbeitet wird

    – MM

    29. Januar 2018 um 8:29 Uhr

Benutzer-Avatar
Arjun Sreedharan

Der Wert der Zeiger ist das gleiche, aber sie sind unterschiedliche Arten. Je nachdem, wie Sie den Zeiger interpretieren, ergibt sich ein Unterschied – zB: Dereferenzieren.

unsigned int *u;
int *d;
unsigned int v = 2147483648; /* 2^31 */
u = &v;
d = (int*) &v;
printf("%u\n", *u);
printf("%d\n", *d);

wird ausgeben:

2147483648
-2147483648

Der Unterschied in der Ausgabe entsteht, weil in printf("%d\n", *d), d wird dereferenziert und gedruckt, als würde es auf a zeigen signed int, außer es ist nicht. Sie müssen also zwischen den beiden Arten von Zeigern in Ihrem Code unterscheiden.

Es kann zeigen, da beide die gleiche Größe haben. Das Problem ist, dass dies einen schwer zu findenden Fehler einführt, da Sie einen vorzeichenbehafteten Wert als einen vorzeichenlosen oder umgekehrt interpretieren.

Benutzer-Avatar
Jim Mcnamara

Ein Zeiger ist eine Zahl, die eine Speicheradresse ist. Zeiger müssen also genügend Genauigkeit haben, um den gesamten Speicher für die Implementierung adressieren zu können.

Ob Sie auf ein signed oder unsigned int verweisen, macht keinen Unterschied in der internen Struktur des Zeigers, da sich das int oder unsigned int theoretisch fast überall im Speicher befinden könnte. Der Datentyp (ohne Vorzeichen) muss deklariert werden, um dem Compiler bei der Entscheidung über die Korrektheit des Codes zu “helfen”.

1365530cookie-checkUnterschied zwischen vorzeichenlosem und vorzeichenbehaftetem int-Zeiger

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy