Frage

Ich bin neu in C, und ich habe diese Frage. warum tut den folgenden Code Absturz:

int *a = 10;
*a = 100;
War es hilfreich?

Lösung

Weil Sie versuchen, 100 auf die Speicherstelle zu schreiben 0X0000000A, die wahrscheinlich zu Ihrem Programm nicht zugeordnet ist. Das heißt,

int *a = 10;

bedeutet nicht, dass der Zeiger ‚a‘ zu einer Stelle im Speicher zeigt den Wert von 10 aufweisen Es bedeutet, es 10 (0x0000000A) im Speicher zu adressieren zeigt. Dann wollen Sie etwas in diese Adresse schreiben, aber Sie haben nicht die „Rechte“, so zu tun, da er nicht zugeordnet ist

Sie können versuchen, die folgenden:

int *a = malloc(sizeof(int));
*a = 100;

Das würde funktionieren, wenn auch schrecklich ineffizient. Wenn Sie nur einen einzigen int benötigen, sollten Sie es nur setzen in den Stapel, nicht der Heap . Auf einem 32-Bit-architecure, ist ein Zeiger 32 Bit lang, und ein int ist 32 Bits lang zu, so dass Sie den Mauszeiger zu einer int-Struktur einnimmt ( mindestens ) 8 Byte Speicherplatz auf diese Weise statt 4. Und wir haben nicht einmal Caching-Probleme erwähnt.

Andere Tipps

Sie müssen die Zeiger auf ein Speicherplatz , nicht willkürlichen Wert (10).

zuweisen
int cell = 10;
int *a = &cell; // a points to address of cell
*a = 100;       // content of cell changed

Siehe meine Antwort zu einem anderen Frage, über das sein vorsichtig mit C .

Ich möchte eine geringfügige Änderung bei der Verwendung von malloc () vorzuschlagen, für alle Antworten, die sie empfehlen die Verwendung von Speicher für den int zuzuweisen. Statt:

a = malloc(sizeof(int));

würde ich vorschlagen, den Typ der Variablen nicht wiederholen, dass, da durch den Compiler bekannt ist und Wiederholen manuell sowohl der Code dichter macht und führt eine Fehlerrisiko. Wenn Sie später die Erklärung ändern, um z.

long *a;

Ohne die Zuordnung zu ändern, würden Sie die falsche Speichermenge am Ende der Zuteilung (im allgemeinen Fall auf 32-Bit-Maschinen int und long sind oft die gleiche Größe). Es ist, IMO, besser zu nutzen:

a = malloc(sizeof *a);

Dies bedeutet einfach „die Größe des Typs zeigte auf, indem ein“, in diesem Fall int, was natürlich ist hier genau richtig. Wenn Sie den Typen in der Erklärung wie oben zu ändern, ist diese Linie immer noch richtig. Es ist immer noch ein Risiko, wenn Sie den Namen der Variablen auf der linken Seite der Zuweisung zu ändern, aber zumindest nicht mehr wiederholen Informationen unnötig.

Beachten Sie auch, dass keine Klammern mit sizeof benötigt werden, wenn es auf den tatsächlichen Objekte (das heißt Variablen) verwenden, nur mit Typnamen, die wie gegossene Ausdrücke aussehen. sizeof ist keine Funktion, es ist ein Operator.

Weil du hast nie Speicher für eine zugeordnet. Sie haben gerade einige Stack-Speicher für einen Zeiger auf eine zugeordnet.

int *a = NULL;

a = malloc (sizeof (int));

if (a != NULL)
{
*a =10;
}

Wird arbeiten.

Alternativ können Sie eine die Adresse einiger vorhandenen Variablen geben, die auch funktionieren würde.

d.

int a* = NULL;
int b = 10;

a = &b;

Das bedeutet nun, dass so etwas wie

tun
*a = 100;

wird auch b gesetzt 100 == werden

Schauen Sie sich diese: http://home.netcom.com/~tjensen/ptr/pointers.pdf

Die folgende Zeile ein,

int *a = 10;

definiert einen Zeiger auf eine Ganzzahl a . Sie dann Punkt der Zeiger eines auf die Speicherstelle 10.

Die nächste Zeile,

*a = 100;

Setzt den Wert 100 in der Speicherstelle darauf durch eine zu.

Das Problem ist:

  1. Sie wissen nicht, wo ein Punkt. (Sie wissen nicht, den Wert der Speicherstelle 10)
  2. überall dort, wo ein Punkt, haben Sie wahrscheinlich kein Recht, diesen Wert zu ändern. Es ist wahrscheinlich ein anderes Programm / Prozess Speicher. Sie Dieb!

Weil Sie einen Zeiger deklarieren int, initialisieren der Zeiger bis 10 (eine Adresse) und dann versuchen, einen Wert in einen int an dieser Adresse zuzuweisen. Da der Speicher an der Adresse 10 nicht an Ihren Prozess gehört, erhalten Sie einen Absturz. Dies sollte funktionieren:

int *a;
a = malloc(sizeof(int));
*a = 10;
printf("a=%i\n", *a);
free(a);

Ist dieser Code selbst kompilieren? 10 ist nicht konvertierbar zu einem int *, wenn Sie es wie so werfen:

int *a = (int *) 10;
*a = 100;

In diesem Fall Sie versuchen, 100 in die Speicheradresse zu schreiben, auf 10. Dies ist nicht in der Regel eine gültige Speicheradresse, damit Ihr Programm stürzt ab.

Es Absturz wahrscheinlich, weil Sie den Mauszeiger auf einen Teil des Speichers zuweisen, die Sie haben keinen Zugriff auf und dann sind Sie etwas Wert auf diesen Speicherplatz zuweisen (die Sie nicht erlaubt sind zu tun!).

Man könnte auch schreiben als:

int* a = 10;
*a = 100;
Hinweis

, um den unterschiedlichen Abstand in der ersten Zeile. Es ist nicht eine beliebte Art, aber ich persönlich denke, es ist klarer. Es hat genau die gleiche Bedeutung für die Compiler.

Dann lesen Sie es laut:

"Pointer-to-int 'a' becomes 10"
"Value-pointed-to-by 'a' becomes 100"

Setzt man den Ist-Wert:

"Value-pointed-to-by 10 becomes 100"

... bei denen man merkt, dass es unwahrscheinlich ist, 10 zu einem Stück Speicher-zu-Punkt Sie verwenden können.

Sie würden so ziemlich nie mit einem wörtlichen zu einem Zeiger zuweisen

int* ptr = (int*)10;  // You've guessed at a memory address, and probably got it wrong
int* ptr = malloc(sizeof(int)); // OS gives you a memory address at runtime  

Ich denke, es könnte sein, einige sehr Low Level-Jobs, wo Sie direkt absolute Speicheradressen angeben. Kernel-Implementierung zum Beispiel?

Okay, versuchen, die einfachste Erklärung heute zu geben, bei dem Versuch, Ihnen detaillierteres Bild darüber geben alles. Lets fügen einige Klammern sollen wir?

(int*) a = 10;
(*a) = 100;

Sie versuchen, vier Bytes in den Adressbereich zu schreiben [10-13]. Das Speicherlayout des Programms beginnt in der Regel höher, so dass Ihre Anwendung versehentlich etwas überschreibt nicht, von wo sie konnte, und noch Funktion (von .data, .bss und Stack zum Beispiel). So endet nur statt Absturz, denn der Adressbereich nicht zugeordnet.

Zeiger zeigt auf einen Speicherplatz und C statische Typisierung definiert einen Typ für einen Zeiger. Obwohl können Sie den Zeiger leicht außer Kraft setzen. Einfach gesagt:

(void*) v = NULL;

Hier gehen wir weiter zu den Dingen. Was ist ein Null-Zeiger? Es ist einfach Zeiger, 0 Adresse auf.

Sie können auch einen Strukturtyp für Ihren Zeiger geben:

struct Hello {
    int id;
    char* name;
};

...

struct Hello* hello_ptr = malloc(sizeof Hello);
hello_ptr->id = 5;
hello_ptr->name = "Cheery";

Ok, was ist malloc? Malloc reserviert Speicher und gibt einen Zeiger auf den zugewiesenen Speicher. Es hat eine folgende Art Signatur:

void* malloc(size_t size);

Wenn Sie nicht über einen konservativen Garbage Collector haben, ist es wahrscheinlich, dass Ihr Speicher wird nicht automatisch freigegeben am Ende wird. Deshalb, wenn Sie aus dem Speicher wieder in Betrieb zu bekommen, was Sie gerade zugewiesen, müssen Sie tun:

free(hello_ptr);

Jeder malloc Sie tun hat eine Größe-Tag in es, so müssen Sie nicht über die Größe des Blocks angeben Sie kostenlos -Routine hingewiesen.

Ok, noch eine Sache, was macht ein Zeichenfolge wie im Speicher aussehen? Die eine ähnliche „Cheery“ zum Beispiel. Einfache Antwort. Es ist ein Null-terminierte Byte-Array.

0.1.2.3.4.5. 6
C h e e r y \0
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top