Ihr Programm stellt aus undefiniertes Verhalten was bedeutet: Es kann buchstäblich alles passieren und es ist immer noch von der Norm als unbestritten abgedeckt. Und wenn ich sage alles, dann meine ich das in vollem Umfang. Das würde sogar für Ihren Computer gelten, der empfindungsfähig wird und Sie die Straße hinunterjagt.
Nun, was in der Regel passiert, aber das ist nicht gerechtfertigt, ist, dass Sie in nicht zugeordneten Adressraum schreiben (auf einem modernen Betriebssystem mit ausgelagertem Speicher), was einen Segmentierungsfehler oder einen Busfehler verursacht (je nach Architektur, Betriebssystem und Laufzeitimplementierung).
ptr
ist ein unitialisierter Zeiger, was bedeutet, dass der Wert des Zeigers noch definiert werden muss. Ein undefinierter Zeiger zeigt per Definition auf nichts und alles, d.h. auf kein gültiges Objekt. Die einzige Möglichkeit, diesen Zeiger gültig zu machen, besteht darin, ihm die Adresse eines richtigen C-Objekts des Typs zuzuweisen, auf den der Zeiger dereferenziert.
Übrigens: Plain C hat sehr, sehr strenge Typisierungsregeln. Ich behaupte manchmal, dass sie sogar strenger sind als die von C++, weil es keinen impliziten Konvertierungsoperator und keine Funktionsüberladung gibt. Aber die schlampige Typisierung und die schlechten Compiler haben seinen Ruf in Bezug auf die Typsicherheit ruiniert.