Mein Zeichenzeiger zeigt auf einen ungültigen Wert, nachdem er von int* gecastet wurde

Lesezeit: 5 Minuten

Benutzeravatar von Mayank Tiwari
Majan Tiwari

Ich lerne die Programmiersprache C, ich habe gerade angefangen zu lernen Arrays mit Zeigern. Ich habe ein Problem in dieser Frage, ich hoffe, das muss ausgegeben werden 5 aber es ist 2Kann jemand bitte erklären, warum?

int main(){
   int arr[] = {1, 2, 3, 4, 5};
   char *ptr = (char *) arr;
   printf("%d", *(ptr+4));
   return 0;
}

  • Wenn jemand diese Frage ablehnt, dann erwähnen Sie bitte Ihren Kommentar, es ist sehr schwierig für mich, hoffentlich nicht für andere …. 🙂

    – Mayank Tiwari

    2. Juli 2013 um 11:07 Uhr

  • Sie haben ein “int”-Array, aber einen “char”-Zeiger.

    – Lukas

    2. Juli 2013 um 11:10 Uhr

  • +1 auf deine Ankündigung 🙂

    – Tagesrai

    2. Juli 2013 um 11:10 Uhr

  • Übrigens hätten Sie erwartet, dass Ihre Ausgabe 5 ist, nicht 4: *ptr zeigt auf das erste Element des Arrays, das 1 ist, vier Elemente danach haben Sie 5. 5 wäre die Ausgabe gewesen, wenn Sie es definiert hätten int *ptr = (int *) arr;

    – Antonio

    2. Juli 2013 um 12:34 Uhr


  • Ich würde vorschlagen, das Thema dieser Frage in etwas Nützlicheres zu ändern. Diese Frage könnte in Zukunft gestellt werden. Ich würde vorschlagen Mein Zeichenzeiger zeigt auf einen gültigen Wert, nachdem er von int * gecastet wurde” oder so etwas. Ich würde die Frage bearbeiten, aber es gibt zu viele Upvotes und ich möchte mich nicht mit einer so beliebten Frage anlegen.

    – Dariusz

    3. Juli 2013 um 7:58 Uhr

Benutzeravatar von Andreas Fester
Andreas Fester

Angenommen, eine Little-Endian-Architektur, bei der ein Int 32 Bit (4 Byte) lang ist, sind die einzelnen Bytes von int arr[] so aussehen (niederwertigstes Byte an der unteren Adresse. Alle Werte in Hex):

|01 00 00 00|02 00 00 00|03 00 00 00|04 00 00 00|05 00 00 00
char *ptr = (char *) arr;

Jetzt, ptr zeigt auf das erste Byte – da hast du gecastet char*wird es als char-Array behandelt:

|1|0|0|0|2|0|0|0|3|0|0|0|4|0|0|0|5|0|0|0
 ^
 +-- ptr

Dann, *(ptr+4) greift auf das fünfte Element des char-Arrays zu und gibt das entsprechende zurück char Wert:

|1|0|0|0|2|0|0|0|3|0|0|0|4|0|0|0|5|0|0|0
         ^
         +-- *(ptr + 4) = 2

Somit, printf() Drucke 2.

Auf einen Big-Endian System, die Reihenfolge der Bytes in jedem int umgekehrt wird, was dazu führt

|0|0|0|1|0|0|0|2|0|0|0|3|0|0|0|4|0|0|0|5
         ^
         +-- *(ptr + 4) = 0

  • Sie mischen Ihre Endianness, Little Endian haben das niedrigste By in der niedrigsten Speicherstelle.

    – Irgendein Programmierer-Typ

    2. Juli 2013 um 11:34 Uhr

  • Ihre Beschreibung, wie printf() behandelt diesen Fall ist falsch. Es erhält den Wert des 5. Zeichens als Ganzzahl, nicht als Zeiger darauf. Außerdem ist, wie Joachim sagt, Ihre Endianness umgedreht.

    – Hasturkun

    2. Juli 2013 um 11:44 Uhr

Der Benutzer-Avatar eines Programmierer-Typen
Irgendein Programmierer

Es liegt an der Größe von char ist eins, und die Größe von int ist vier. Dies bedeutet das Hinzufügen 4 zu ptr macht das Ergebnis auf den zweiten Eintrag in der int Reihe.

Wenn Sie dies auf einem großen kompiliert haben endian System hätten Sie stattdessen 33554432 gedruckt.

  • Ich dachte, dass Endian nur für Gleitkommazahlen gilt. Schlagen Sie vor, dass sich ganze Zahlen genauso verhalten? Ich bin mir nicht sicher.

    – Bathseba

    2. Juli 2013 um 11:15 Uhr


  • Überall dort, wo ein Typ mehr als 1 Byte verwendet, stellt sich die Frage, in welcher Reihenfolge die Bytes gespeichert werden.

    – Jo

    2. Juli 2013 um 11:16 Uhr

  • @Bathsheba Endianess ist bestimmt ein ganzzahliges Problem.

    – Irgendein Programmierer-Typ

    2. Juli 2013 um 11:17 Uhr

  • @JoachimPileborg +1 – Ich erinnere mich, dass ich stets vermasseln sie 😀

    – Andreas Fester

    2. Juli 2013 um 12:02 Uhr

  • … und ich denke, dass Sie von Anfang an Recht hatten: Bei Big Endian sollte das Ergebnis Null sein, da Sie auf das fünfte Byte als zugreifen char und dieses byte ist null … sorry dafür …

    – Andreas Fester

    2. Juli 2013 um 12:18 Uhr

int main(){
 int arr[] = {1,2,3,4,5};
 char *ptr = (char *) arr;
 printf("%d",*(ptr+4));
 return 0;
}

Jeder Fall von arr hat sizeof(int) Größe (die bei Ihrer Implementierung 4 sein kann).

Seit ptr ist ein Hinweis auf char, Zeigerarithmetik macht ptr + 4 Punkte 4 Bytes nach &arr[0]die sein kann &arr[1].

Im Speicher sieht es so aus:

Address | 0 1 2 3 | 4 5 6 7 | ...
Value   |  arr[0] |  arr[1] | ...

Was Sie tun, ist im Produktionscode definitiv nicht empfehlenswert, aber es ist definitiv großartig, um Zeiger, Umwandlungen usw. im Lernprozess zu verstehen, daher ist Ihr Beispiel großartig. Also, warum bekommen Sie 2. Es liegt daran, dass Ihr Array ein Array von Ints ist, die je nach Ihrer Architektur eine unterschiedliche Größe haben (in Ihrem Fall sizeof(int) ist 4). Sie definieren ptr als Zeichenzeiger hat char eine Größe von 1 Byte. Zeigerarithmetik (das macht man beim Schreiben ptr+4) arbeitet mit der Größe von Objekten, auf die der Zeiger verweist, in Ihrem Fall mit Zeichen. Daher ptr+4 ist 4 Bytes vom Anfang Ihres Arrays entfernt und somit an der 2. Position Ihres int Reihe. Das ist es. Versuchen ptr+5du solltest 0 bekommen.

Benutzeravatar von Bathsheba
Bathseba

Auf einer 32-Bit-Plattform int ist viermal so groß wie char. Wenn Sie 4 zu addieren ptrSie addieren das 4-fache der Größe dessen, worauf ptr zeigt zu ptr (das selbst ein Speicherort ist). Das ist zufällig die Adresse des zweiten Elements in der int Reihe.

Auf einer 64-Bit-Plattform int ist acht mal so groß wie char; und Ihre Ausgabe wäre sehr unterschiedlich.

Um es kurz zu machen, Ihr Code ist nicht portabel (siehe auch Joachim Pileborgs Antwort auf Endianness), aber es macht Spaß, ihn zu entfernen.

  • int Die Speichergröße ist implementierungsabhängig. Auf den meisten 64-Bit-Plattformen sizeof(int) ist 4. Weitere Informationen finden Sie unter stackoverflow.com/questions/384502/….

    – Matthieu Rouget

    2. Juli 2013 um 11:53 Uhr


Benutzeravatar von dijkstra
dijkstra

Da Sie int* in char* umwandeln, ptr[0] = 1, Ptr[4] = 2, Ptr[8] = 3, Ptr[12] = 4 , Ptr[16] = 5 und alle anderen gleich 0. ptr+4 zeigt auf das 4. Element im ptr-Array. Ergebnis ist also 2.

  • int Die Speichergröße ist implementierungsabhängig. Auf den meisten 64-Bit-Plattformen sizeof(int) ist 4. Weitere Informationen finden Sie unter stackoverflow.com/questions/384502/….

    – Matthieu Rouget

    2. Juli 2013 um 11:53 Uhr


Benutzeravatar von noney
nein

int main(){
 int arr[] = {1,2,3,4,5};
 char *ptr = (char *) arr;
 printf("%d",*(ptr+4));
 return 0;
}

Vorstellen arr wird unter der Adresse gespeichert 100 (total dumme Adresse). Also hast du:
arr[0] wird unter der Adresse 100 gespeichert.
arr[1] wird unter der Adresse 104 gespeichert. (Aufgrund des Typs gibt es +4 int)
arr[2] wird unter der Adresse 108 gespeichert.
arr[3] wird unter der Adresse 112 gespeichert. Etc etc.

jetzt machst du es char *ptr = (char *) arr;Also ptr = 100 (dasselbe wie arr). Die nächste Aussage ist interessant, besonders das zweite Argument von printf : *(ptr+4). Behalte das im Hinterkopf ptr = 100. Also ptr + 4 = 104, die gleiche Adresse, dass arr[1] ! Es wird also der Wert von gedruckt arr[1]das ist 2.

1410090cookie-checkMein Zeichenzeiger zeigt auf einen ungültigen Wert, nachdem er von int* gecastet wurde

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

Privacy policy