Jede Art von Zeiger kann auf irgendetwas zeigen?

8

Stimmt diese Aussage? Kann irgendein "TYP" des Zeigers auf irgendeinen anderen Typ zeigen? Weil ich das glaube, habe noch Zweifel.

Warum werden Zeiger für bestimmte Typen deklariert? Z.B. int oder char ?

Die einzige Erklärung, die ich bekommen konnte, war: Wenn ein Zeiger vom Typ int auf ein char -Array zeigte, dann springt der Zeiger bei der Inkrementierung des Zeigers von der 0-Position zur 2-Position und überspringt dabei 1 Position zwischen (weil int size = 2).

Und vielleicht, weil ein Zeiger nur die Adresse eines Wertes enthält, nicht den Wert selbst, d. h. int oder double .

Habe ich mich geirrt? War diese Aussage richtig?

    
Abhinav Gauniyal 31.10.2013, 15:28
quelle

4 Antworten

7

Zeiger können austauschbar sein, sind aber nicht erforderlich.

Insbesondere müssen auf bestimmten Plattformen bestimmte Typen an bestimmte Bytegrenzen angepasst werden. Während also ein char irgendwo im Speicher sein kann, muss sich ein int möglicherweise auf einer 4-Byte-Grenze befinden.

Ein weiterer wichtiger potenzieller Unterschied besteht in Funktionszeigern.
Pointer zu Funktionen sind möglicherweise nicht mit Zeigern zu Datentypen auf vielen Plattformen austauschbar.

Es muss wiederholt werden: Dies ist plattformspezifisch .

Ich glaube, Intel x86-Architekturen behandeln alle Zeiger gleich.
Aber möglicherweise begegnen Sie anderen Plattformen, wo das nicht stimmt.

    
abelenky 31.10.2013, 15:34
quelle
4

Jeder Zeiger hat einen bestimmten Typ. Es gibt einen speziellen generischen Zeigertyp void* , der auf alles zeigen kann, aber Sie müssen ein void* in einen bestimmten Zeigertyp konvertieren, bevor Sie es dereferenzieren können.

Sie können einen Zeigerwert von einem Zeigertyp in einen anderen konvertieren. In den meisten Fällen wird die Konvertierung eines Zeigers von foo* nach bar* und zurück nach foo* den ursprünglichen Wert ergeben - aber das ist nicht immer in allen Fällen garantiert.

Sie können bewirken, dass ein Zeiger vom Typ foo* auf ein Objekt vom Typ bar zeigt, aber (a) ist es normalerweise eine schlechte Idee und (b) in einigen Fällen sogar funktioniert möglicherweise nicht (wenn die Zieltypen foo und bar unterschiedliche Größen oder Ausrichtungsanforderungen haben).

Du kannst mit Dingen wie:

durchkommen %Vor%

was bewirkt, dass p auf n zeigt - aber dann gibt *p Ihnen nicht den Wert von n , es gibt Ihnen den Wert des ersten Bytes von n als char .

Das unterschiedliche Verhalten der Zeigerarithmetik ist nur ein Teil des Grundes für unterschiedliche Zeigertypen. Es geht hauptsächlich um Typ Sicherheit . Wenn Sie einen Zeiger vom Typ int* haben, können Sie einigermaßen sicher sein (es sei denn, Sie haben etwas unsicher gemacht), dass er tatsächlich auf ein int -Objekt zeigt. Und wenn Sie versuchen, es als ein Objekt eines anderen Typs zu behandeln, wird der Compiler wahrscheinlich darüber beschweren.

Im Grunde haben wir verschiedene Zeigertypen aus denselben Gründen, aus denen wir andere eindeutige Typen haben: So können wir mit Hilfe des Compilers verfolgen, welche Art von Wert in jedem Objekt gespeichert ist.

(Es gab Sprachen, die nur generische Zeiger nicht typisiert haben. In einer solchen Sprache ist es schwieriger, Typfehler zu vermeiden, wie das Speichern eines Wertes eines Typs und den versehentlichen Zugriff auf einen anderen Typ.)

    
Keith Thompson 31.10.2013 15:35
quelle
3

Jeder Zeiger kann sich auf einen beliebigen Ort im Speicher beziehen, also ist die Aussage technisch korrekt. Wenn Sie das sagen, müssen Sie bei der Neuinterpretation von Zeigertypen vorsichtig sein.

Ein Zeiger hat grundsätzlich zwei Informationen: einen Speicherort und den Typ, den erwartet , um ihn zu finden. Der Speicherort könnte alles sein. Es könnte der Ort sein, an dem ein Objekt oder Wert gespeichert wird; es könnte in der Mitte einer Textzeile stehen; oder es könnte einfach ein willkürlicher Block nicht initialisierten Speichers sein.

Die Typinformation in einem Zeiger ist jedoch wichtig. Die Array- und Zeigerarithmetikerklärung in Ihrer Frage ist korrekt - wenn Sie versuchen, Daten im Speicher mit einem Zeiger zu durchlaufen, muss der Typ korrekt sein, andernfalls können Sie nicht korrekt iterieren. Dies liegt daran, dass verschiedene Typen unterschiedliche Größen haben und möglicherweise anders ausgerichtet sind.

Der Typ ist auch wichtig in Bezug darauf, wie Daten in Ihrem Programm gehandhabt werden. Wenn Sie beispielsweise int im Speicher gespeichert haben, aber Sie darauf zugreifen, indem Sie einen float* -Zeiger dereferenzieren, erhalten Sie wahrscheinlich nutzlose Ergebnisse (es sei denn, Sie haben es aus einem bestimmten Grund so programmiert). Dies liegt daran, dass ein int im Speicher anders gespeichert wird als ein float .

    
Peter Bloomfield 31.10.2013 15:42
quelle
1
  

Kann irgendein "TYPE" des Zeigers auf irgendeinen anderen Typ zeigen?

Im Allgemeinen keine. Die Typen müssen verwandt sein.

Es ist möglich, reinterpret_cast zu verwenden, um einen Zeiger von einem Typ auf einen anderen zu übertragen, aber wenn diese Zeiger nicht mit einem static_cast legal konvertiert werden können, ist reinterpret_cast ungültig. Daher können Sie Foo* foo = ...; Bar* bar = (Bar*)foo; nicht verwenden, außer Foo und Bar sind tatsächlich verwandt.

Sie können auch reinterpret_cast verwenden, um von einem Objektzeiger auf ein void* zu casten und umgekehrt, und in diesem Sinne kann void* auf alles zeigen - aber das ist nicht das, wonach Sie zu fragen scheinen.

Außerdem können Sie reinterpret_cast vom Objektzeiger zum Integralwert und umgekehrt, aber wiederum nicht das, was Sie zu fragen scheinen.

Schließlich wird eine spezielle Ausnahme für char* gemacht. Sie können eine char* -Variable mit der Adresse eines anderen Typs initialisieren und eine Zeigermathematik für den resultierenden Zeiger ausführen. Du kannst immer noch nicht durch den Zeiger dereferenzieren, wenn das Ding, auf das gezeigt wird, nicht tatsächlich ein char ist, aber es kann dann wieder auf den tatsächlichen Typ zurückgeworfen und auf diese Weise verwendet werden.

Bedenken Sie auch, dass Sie jedes Mal, wenn Sie reinterpret_cast in einem Kontext verwenden, am Abgrund einer Klippe tanzen. Dereferenzieren eines Zeigers auf ein Foo , wenn das Ding, auf das es tatsächlich zeigt, ein Bar ist, liefert Undefined Behavior, wenn die Typen nicht verwandt sind. Sie würden gut tun, um diese Arten von Güssen um jeden Preis zu vermeiden.

    
John Dibling 31.10.2013 15:38
quelle

Tags und Links