2013-07-15 7 views
8

Ich habe gerade mit dem Lernen von C begonnen und ich habe einige einfache Programme mit MinGW für Windows ausgeführt, um zu verstehen, wie Zeiger funktionieren. Ich habe versucht, die folgenden:Direkte Zuordnung von Werten zu C-Zeigern

#include <stdio.h> 

int main(){ 
    int *ptr; 
    *ptr = 20; 
    printf("%d", *ptr); 
    return 0; 
} 

, die richtig kompiliert, aber wenn ich die ausführbare Datei ausführen funktioniert es nicht - der Wert nicht auf die Kommandozeile gedruckt wird, statt eine Fehlermeldung erhalten, dass die EXE-Datei, sagt funktioniert nicht mehr.

jedoch als ich versuchte, den Wert in eine Variable, und weisen int * ptr an die Speicheradresse der Variablen zu speichern, wie unten gezeigt:

#include <stdio.h> 

int main(){ 
    int *ptr; 
    int q = 50; 
    ptr = &q; 
    printf("%d", *ptr); 
    return 0; 
} 

es gut funktioniert.

Meine Frage ist, warum kann ich nicht direkt einen literalen Wert auf den Zeiger setzen? Ich habe Tutorials online nach Zeigern angeschaut und die meisten von ihnen machen es genauso wie das zweite Beispiel.

Jede Hilfe wird geschätzt.

+0

Ursache dieser Zeiger ist nicht initialisiert - es kann auf so ziemlich überall zeigen und das Programm möglicherweise abstürzen. – Till

+1

Sie hatten Glück, dass es mit einem Fehler beendet wurde. – JonnyRo

+1

@JonnyRo hat Recht. In echtem Code führt diese Art von Bug dazu, dass entweder eine Woche lang Debugging-Sitzungen durchgeführt werden, um herauszufinden, warum sich eine andere Variable gelegentlich zufällig ändert (niemals, wenn Sie tatsächlich dafür testen, immer wenn Sie es tun) eine öffentliche Demonstration) oder Sicherheits-Exploits, bei denen jemand das Flag "is_admin" auf True setzt, indem er verschiedene Werte manipuliert. – abarnert

Antwort

20

Das Problem besteht darin, dass Sie den Zeiger nicht initialisieren. Sie haben einen Zeiger auf "wo immer Sie möchten" erstellt. Dies kann die Adresse einer anderen Variablen oder die Mitte des Codes oder ein Speicher sein, der überhaupt nicht zugeordnet ist.

Sie müssen eine int Variable irgendwo im Speicher für die int * Variable auf zeigen.

Ihr zweites Beispiel tut dies, aber es macht andere Dinge, die hier nicht relevant sind. Hier ist die einfachste Sache, die Sie tun müssen:

int main(){ 
    int variable; 
    int *ptr = &variable; 
    *ptr = 20; 
    printf("%d", *ptr); 
    return 0; 
} 

Hier wird die int Variable wird nicht initialisiert, aber das ist in Ordnung, weil Sie nur, was Wert gehen zu ersetzen war dort mit 20. Der Schlüssel ist, dass der Zeiger initialisiert wird, um auf die variable zu zeigen. In der Tat könnte man nur etwas rohen Speicher zuordnen zu zeigen auf, wenn Sie wollen:

int main(){ 
    void *memory = malloc(sizeof(int)); 
    int *ptr = (int *)memory; 
    *ptr = 20; 
    printf("%d", *ptr); 
    free(memory); 
    return 0; 
} 
1

Im ersten Beispiel hat ptr nicht initialisiert worden ist, so dass es zu einer nicht spezifizierten Speicherstelle verweist. Wenn Sie diesem unbestimmten Ort etwas zuweisen, explodiert Ihr Programm.

Im zweiten Beispiel wird die Adresse gesetzt, wenn Sie ptr = & q sagen, also sind Sie in Ordnung.

7

erstes Programm mit Kommentaren

#include <stdio.h> 

int main(){ 
    int *ptr;    //Create a pointer that points to random memory address 

    *ptr = 20;   //Dereference that pointer, 
          // and assign a value to random memory address. 
          //Depending on external (not inside your program) state 
          // this will either crash or SILENTLY CORRUPT another 
          // data structure in your program. 

    printf("%d", *ptr); //Print contents of same random memory address 
          // May or may not crash, depending on who owns this address 

    return 0;    
} 

zweites Programm mit Kommentaren

#include <stdio.h> 

int main(){ 
    int *ptr;    //Create pointer to random memory address 

    int q = 50;   //Create local variable with contents int 50 

    ptr = &q;    //Update address targeted by above created pointer to point 
          // to local variable your program properly created 

    printf("%d", *ptr); //Happily print the contents of said local variable (q) 
    return 0; 
} 

Der Schlüssel ist, dass Sie keinen Zeiger verwenden können, bis Sie wissen, dass es zu einer Adresse zugeordnet ist, die Sie selbst haben es geschafft, entweder indem Sie auf eine andere von Ihnen erstellte Variable oder auf das Ergebnis eines malloc-Aufrufs zeigen.

Verwenden Sie es vor dem Erstellen von Code, der auf nicht initialisierten Speicher abhängt, der im besten Fall abstürzt, aber im schlimmsten Fall manchmal funktioniert, weil die zufällige Speicheradresse innerhalb des Speicherplatzes ist, den Ihr Programm bereits besitzt. Gott hilft dir, wenn es eine Datenstruktur überschreibt, die du woanders in deinem Programm verwendest.

+1

Schöne Illustration. – abarnert

Verwandte Themen