Nicht verstanden, was der Ausdruck *(uint32_t*) bewirkt

Lesezeit: 4 Minuten

Benutzeravatar von Hoa.N
Hoa.N

Ich verstehe den Ausdruck nicht *(uint32_t*) tut.

Ich habe die Anweisung auf ein Beispiel heruntergebrochen, das die Teile deklariert, damit ich versuchen kann, zu interpretieren, was jeder tut.

  uint32_t* ptr;
  uint32_t num
  *(uint32_t*)(ptr + num); // <-- what does this do?

Ich verstehe das letzte Bit im Beispiel nicht, was passiert, wenn der Ausdruck *(uint32_t*)(ptr + num); wird zur Laufzeit ausgeführt?

  • Diese Besetzung ist hier nutzlos. Eigentlich ist der ganze Ausdruck. ptr + num ist uint32_t * ohnehin.

    – Eugen Sch.

    16. Februar 2018 um 19:58 Uhr


  • Beachten Sie, dass diese Definition erschien zuerst in C99.

    – mpontillo

    9. April 2019 um 5:18 Uhr

  • Muss sagen, angesichts der Definitionen hier, *(uint32_t*)(ptr + num) ist in der Tat dasselbe wie *(ptr + num)was natürlich ist ptr[num]. Diese letztere Form ist IMHO vorzuziehen

    – Bobbogo

    23. April 2019 um 14:36 ​​Uhr


  • Macht es was?

    – Peter Mortensen

    26. April 2021 um 12:48 Uhr

Pablos Benutzeravatar
Pablo

uint32_t ist ein numerischer Typ, der 32 Bit garantiert. Der Wert ist vorzeichenlos, was bedeutet, dass der Wertebereich von 0 bis 2 reicht32 – 1.

Dies

uint32_t* ptr;

deklariert einen Zeiger vom Typ uint32_t*, aber der Zeiger ist nicht initialisiert, d. h. der Zeiger zeigt auf nichts Bestimmtes. Der Versuch, über diesen Zeiger auf den Speicher zuzugreifen, führt zu undefiniertem Verhalten und Ihr Programm kann abstürzen.

Dies

uint32_t num;

ist nur eine Variable vom Typ uint32_t.

Dies

*(uint32_t*)(ptr + num);

ptr + num gibt Ihnen einen neuen Zeiger zurück. Sie wird Zeigerarithmetik genannt. Es ist wie normale Arithmetik, nur dass der Compiler die Größe von Typen berücksichtigt. Denk an ptr + num als Speicheradresse basierend auf dem Original ptr Zeiger plus die Anzahl der Bytes für num uint32_t Objekte.

Das (uint32_t*) x ist eine Besetzung. Dies teilt dem Compiler mit, dass er den Ausdruck behandeln soll x als wäre es ein uint32_t*. In diesem Fall ist es nicht einmal erforderlich, weil ptr + num ist schon ein uint32_t*.

Das * Am Anfang steht der Dereferenzierungsoperator, mit dem über einen Zeiger auf den Speicher zugegriffen wird. Der gesamte Ausdruck ist äquivalent zu

ptr[num];

Da keine dieser Variablen initialisiert wird, ist das Ergebnis Müll.

Wenn Sie sie jedoch wie folgt initialisieren:

uint32_t arr[] = { 1, 3, 5, 7, 9 };
uint32_t *ptr = arr;
uint32_t num = 2;

printf("%u\n", *(ptr + num));

dies würde 5 drucken, weil ptr[2] ist 5.

  • OK bis auf den printf-Bezeichner. "%" PRIu32 ist besser. "%u" Streichhölzer unsigned.

    – chux – Wiedereinsetzung von Monica

    16. Februar 2018 um 20:09 Uhr


  • @chux huy der Tastaturgremlin hat mich angegriffen, so viele “Tippfehler”. Ich habe die repariert printf Spezifizierer, daran habe ich nicht gedacht.

    – Pablo

    16. Februar 2018 um 20:11 Uhr

  • was ist dann der unterschied zw uint32_t und int32_t

    – Travis Su

    2. Februar 2020 um 0:30 Uhr

  • @TravisSu lies den ersten Satz meiner Antwort. uint32_t ist für vorzeichenlose 32-Bit-Ganzzahlen, dh es speichert Werte zwischen 0 und 4294967295 und int32_t ist für vorzeichenbehaftete 32-Bit-Ganzzahlen, was bedeutet, dass es Werte zwischen -2147483648 und 2147483647 speichert.

    – Pablo

    2. Februar 2020 um 3:13 Uhr

  • selbstlernendes Python und das ist sehr klar, danke

    – Nudeln

    16. November 2021 um 4:41 Uhr

Benutzeravatar von user7610
Benutzer7610

uint32_t ist darin definiert stdint.halso muss man es vielleicht einschließen

#include <stdint.h>

diese Überschrift definieren soll uint32_t ein vorzeichenloser ganzzahliger Typ sein, der genau 32 Bits benötigt.

  • Dieser Kommentar beantwortet nicht die Frage „Was ist *(uint32_t*)?”

    – Ludin

    4. Juni 2020 um 11:47 Uhr

  • Fügen Sie dies lieber als Kommentar hinzu

    – Haseeb Mir

    25. September 2021 um 15:19 Uhr

Benutzeravatar von giusti
giusti

Das bringt nicht wirklich was. Lassen Sie mich Ihnen ein anderes Beispiel geben:

uint32_t data;
void *pointer = &data;
*(uint32_t *)pointer = 5;

Zuerst, void* bedeutet “generischer” Zeiger. Es kann auf Objekte beliebigen Typs zeigen.

Jetzt, (uint32_t *) bedeutet „interpretieren pointer als Zeiger auf ein Objekt mit Typ uint32_t.

Der Rest des Ausdrucks bedeutet einfach “5 an der von diesem Zeiger gespeicherten Stelle speichern”.

Wenn Sie wissen wollen, was uint32_t Das ist eine Ganzzahl ohne Vorzeichen mit genau 32 Bit. Und pointer + num ist die gleiche wie die Adresse von pointer[5].

  • void *pointer = &data; ist gültiges C++. Ist die implizite Konvertierung von void * auf andere Zeigertypen, die in C++ ungültig ist.

    – HolyBlackCat

    16. Februar 2018 um 20:14 Uhr


Diese Art von Ausdruck wird normalerweise beim Wortspiel verwendet. Wenn Sie mit Typ-Wortspielen nicht vertraut sind, besteht die Hauptidee darin, das Typsystem zu umgehen, damit Sie etwas als einen anderen Typ behandeln können, als es wirklich ist (dh ein int a als doppelt behandeln).

Die Hauptidee hinter Typ-Punning ist, dass Sie einen Zeiger auf eine aktuelle Variable nehmen und ihn dann in einen anderen Typ umwandeln, indem Sie ihn in einen Zeiger dieses Typs umwandeln und ihn dann dereferenzieren, daher die häufig verwendete Umwandlung und Dereferenzierung, auf die Sie sich beziehen ( *(uint32_t *) = Umwandlung in vorzeichenlosen 32-Bit-Int-Zeiger und dann Dereferenzierung).

Wie andere bereits betont haben, macht Ihr Code “nichts”, weil Sie ein Int mit einem Int vertauschen, was keine Wirkung hat. Wenn Sie jedoch ein Int in ein Double punzieren wollten …

uint32_t num=5;
double& myvar=*(double*) &num;

Jetzt können Sie manipulieren nums Speicher als Double Via myvar wenngleich num ist noch ein Int. Dies ist eine schreckliche Idee und soll nur als Spielzeugbeispiel für die Verwendung von Wortspielen dienen.

1433630cookie-checkNicht verstanden, was der Ausdruck *(uint32_t*) bewirkt

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

Privacy policy